asp.net mvc keep object alive, information - asp.net-mvc

i have this code
[HttpPost]
public ActionResult Index(LoginModel loginModel)
{
if (ModelState.IsValid)
{
// some lines of code . bla bla bla
TempData["loginModel"] = loginModel;
return RedirectToAction("index", "premium");
}
...
}
and this controller here
public ActionResult Index()
{
var loginModel = TempData["loginModel"] as LoginModel;
...
}
now, when the page loads, everything seems to work fine. but when i refresh, everything messes up, it says that the loginModel is like null. the question is, how can i like keep track of the current login users. i have forms authentication enabled. tnx
error is as below
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 22:
Line 23: var loginModel = TempData["loginModel"] as LoginModel;
Line 24: string username = loginModel.username;
Line 25: string password = loginModel.password;
Line 26: premiumModel.username = username;

Confusion
but when i refresh, everything messes up, it says that the loginModel
is like null
Answer
This is due to the fact that you have read the TempData key and Once it is read, data will be lost for that particular key.
var Value = TempData["keyName"] //Once read, data will be lost
Question
how can i like keep track of the current login users
Answer
So to persist the data even after the data is read you can Alive it like below
var Value = TempData["keyName"];
TempData.Keep(); //Data will not be lost for all Keys
TempData.Keep("keyName"); //Data will not be lost for this Key
TempData works in new Tabs/Windows also, like Session variable does.
You could use Session Variable also, Only major problem is that Session Variable are very heavy comparing with TempData. Finally you are able to keep the data across Controllers/Area also.
Hope this post will help you alot.

You only need to store the user's identity (username) once the user is authenticated - password is not needed. As such ASP.NET authentication already supports storing user's identity in the authentication cookie and you don't have to re-invent the wheel. You can get the identity using Controller.User property.
EDIT: I am assuming that you have set up your application correctly for Forms Authentication. Regardless, here are few how-to/tutorial links that start you on it:
http://www.apexa.net/Blog/web_design_Blog_20100319.aspx
http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication-cs
Explain solution so that you don't have to apply Authorize attribute on every action - http://blogs.msdn.com/b/rickandy/archive/2011/05/02/securing-your-asp-net-mvc-3-application.aspx

TempData does only live for one request. Therefore it's empty when you make the second request. If you'd want to do it like this you should use Session instead or you can have a look at forms authentication.
You should also consider VinayC advice and not store any password information in any state, especially not in clear text format.

I suggest you create a new MVC 3 project in Visual Studio via File > New. It will set up forms authentication for you, so you can see the best practices for the login and registration pages, signing the user in/out with the session cookie, and displaying user info like username.

Related

ASP.NET MVC 5 : get login username not pc user name [duplicate]

In a forms model, I used to get the current logged-in user by:
Page.CurrentUser
How do I get the current user inside a controller class in ASP.NET MVC?
If you need to get the user from within the controller, use the User property of Controller. If you need it from the view, I would populate what you specifically need in the ViewData, or you could just call User as I think it's a property of ViewPage.
I found that User works, that is, User.Identity.Name or User.IsInRole("Administrator").
Try HttpContext.Current.User.
Public Shared Property Current() As
System.Web.HttpContext
Member of System.Web.HttpContext
Summary:
Gets or sets the System.Web.HttpContext object for the current HTTP request.
Return Values:
The System.Web.HttpContext for the current
HTTP request
You can get the name of the user in ASP.NET MVC4 like this:
System.Web.HttpContext.Current.User.Identity.Name
I realize this is really old, but I'm just getting started with ASP.NET MVC, so I thought I'd stick my two cents in:
Request.IsAuthenticated tells you if the user is authenticated.
Page.User.Identity gives you the identity of the logged-in user.
I use:
Membership.GetUser().UserName
I am not sure this will work in ASP.NET MVC, but it's worth a shot :)
getting logged in username: System.Web.HttpContext.Current.User.Identity.Name
UserName with:
User.Identity.Name
But if you need to get just the ID, you can use:
using Microsoft.AspNet.Identity;
So, you can get directly the User ID:
User.Identity.GetUserId();
In order to reference a user ID created using simple authentication built into ASP.NET MVC 4 in a controller for filtering purposes (which is helpful if you are using database first and Entity Framework 5 to generate code-first bindings and your tables are structured so that a foreign key to the userID is used), you can use
WebSecurity.CurrentUserId
once you add a using statement
using System.Web.Security;
We can use following code to get the current logged in User in ASP.Net MVC:
var user= System.Web.HttpContext.Current.User.Identity.GetUserName();
Also
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; //will give 'Domain//UserName'
Environment.UserName - Will Display format : 'Username'
This page could be what you looking for:
Using Page.User.Identity.Name in MVC3
You just need User.Identity.Name.
Use System.Security.Principal.WindowsIdentity.GetCurrent().Name.
This will get the current logged-in Windows user.
For what it's worth, in ASP.NET MVC 3 you can just use User which returns the user for the current request.
If you are inside your login page, in LoginUser_LoggedIn event for instance, Current.User.Identity.Name will return an empty value, so you have to use yourLoginControlName.UserName property.
MembershipUser u = Membership.GetUser(LoginUser.UserName);
You can use following code:
Request.LogonUserIdentity.Name;
IPrincipal currentUser = HttpContext.Current.User;
bool writeEnable = currentUser.IsInRole("Administrator") ||
...
currentUser.IsInRole("Operator");
var ticket = FormsAuthentication.Decrypt(
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
if (ticket.Expired)
{
throw new InvalidOperationException("Ticket expired.");
}
IPrincipal user = (System.Security.Principal.IPrincipal) new RolePrincipal(new FormsIdentity(ticket));
If you happen to be working in Active Directory on an intranet, here are some tips:
(Windows Server 2012)
Running anything that talks to AD on a web server requires a bunch of changes and patience. Since when running on a web server vs. local IIS/IIS Express it runs in the AppPool's identity so, you have to set it up to impersonate whoever hits the site.
How to get the current logged-in user in an active directory when your ASP.NET MVC application is running on a web server inside the network:
// Find currently logged in user
UserPrincipal adUser = null;
using (HostingEnvironment.Impersonate())
{
var userContext = System.Web.HttpContext.Current.User.Identity;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["AllowedDomain"], null,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
adUser = UserPrincipal.FindByIdentity(ctx, userContext.Name);
}
//Then work with 'adUser' from here...
You must wrap any calls having to do with 'active directory context' in the following so it's acting as the hosting environment to get the AD information:
using (HostingEnvironment.Impersonate()){ ... }
You must also have impersonate set to true in your web.config:
<system.web>
<identity impersonate="true" />
You must have Windows authentication on in web.config:
<authentication mode="Windows" />
In Asp.net Mvc Identity 2,You can get the current user name by:
var username = System.Web.HttpContext.Current.User.Identity.Name;
In the IIS Manager, under Authentication, disable:
1) Anonymous Authentication
2) Forms Authentication
Then add the following to your controller, to handle testing versus server deployment:
string sUserName = null;
string url = Request.Url.ToString();
if (url.Contains("localhost"))
sUserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
else
sUserName = User.Identity.Name;
If any one still reading this then, to access in cshtml file I used in following way.
<li>Hello #User.Identity.Name</li>

MVC passing values through several views

I have a login view for a user to authenticate: after he inserts his username and password, the next view has a section with welcome, username message. I pass this information through a ViewBag.welcomeMsg and everything is smooth.
When I advance to another view, that section no longer contains the message as the ViewBag.welcomeMsg is defined in the first login controller and gets erased after that.
I don't want write in every controller ViewBag.welcomeMsg = "...";
My question: is there a way to pass a variable like ViewBag that persists and can be accessed from every view of the web application? Like a static field?
If you just want to show the welcome message on your view when user is authenticated then just modify your view like this :
#if (Request.IsAuthenticated)
{
<text>Welcome, #User.Identity.Name</text>
}
Can check with the TempData which will be available till start of the next view rendering. so that you can set it to the other viewbag from tempData.
It very much depends on how you handle the authentication process. If you are using FormsAuthentication for example, then the user information will be stored in User.Identity.Name. You can access User property from various contexts like controller, view, etc.
On the other hand if you are handling the authentication by yourself, my suggestion to you would be to do any of the following (I am writing this from top of my mind, so if I miss a name of a property, forgive me):
Store username in a cookie, and in Global.asax handle PostAuthenticated event where you will read the username (if authenticated) from the cookie. After that create a GenericPrincipal object with GenericIdentiy and assign it to a Controller.User
Store the information in a session (the easiest of all) and pass it around. However, the problem with this is if you have a sessionless controller in which case you cannot rely on this approach.
I wrote an article a long time ago about working with roles and principals, but you can get a picture on how to handle your problem with this solution http://mvcdeveloper.wordpress.com/2013/06/08/passing-user-roles-to-httpcontext-user/

How do I pass the userId into the model ASP.NET MVC?

I've had a thorough search around but really can't find anything addressing the scenario I'm facing (oddly because I'd have thought it's quite a common thing to do).
Background
I'm creating an application with ASP.NET MVC 4 and Entity Framework 5 Code First. For the purpose of this question, think of it as a blogging application with posts and users.
Project
The post model requires that every post have a corresponding UserId.
With the ASP.NET MVC 4 Membership it is easy to find the username of the person logged in with
User.Identity.Name.
This isn't ideal, we want the ID, but a query such as this can search the db for the name and get the ID.
db.UserProfiles.Single(a => a.UserName == User.Identity.Name);
Problem
The problem arises when trying to create a post. Model.IsValid is false, as no UserId is being passed in from the view. Obviously, as the user isn't expected to enter their ID.
I've tried putting the ID value into the ViewBag and using a #Html.Hidden() field in the view, however I've had no success with this. Model.IsValid always returns false.
Should this information be input through the create view? Or should it be done directly in the controller? Its quite a frustrating problem as I have the information and just need to figure how to pass it into the model.
CONTROLLER CODE
This is basically just the default scaffolded code. The commented code is how I tried setting the model value directly from the controller, however that was little more than trial and error.
//
// POST: /Post/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Post post)
{
if (ModelState.IsValid)
{
//var userId = db.UserProfiles.Single(a => a.UserName == User.Identity.Name);
//post.User.UserId = userId.UserId;
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(post);
}
Be careful with hidden fields. Anyone could put whatever value they want in that field (i.e. they could spoof another user). You'd be better off caching the ID in the session at login, and using that value.
This is a typical case where you want to create an EditModel as a data transfer object (DTO) between your view and controller layers.
Create a class BlogPostEditModel that has all properties you need the user to fill in when creating a new blog post. Then, map this type (e.g. using AutoMapper) to your BlogPost entity, and fill in the user ID as well.
To use built-in validation such as Model.IsValid(), put the data annotations attributes on the DTO instead.
Honestly, I would have the value assigned via the controller. If you had someone messing with your html via Firebug, they could actually change the id before it was passed and submitted to your form. I would remove it from your Create view and submit from the controller.

How do I STOP model data appearing in the URL

How can I pass a viewmodel to a view without the model's data showing up in the URL?
public ActionResult MyView(MyModel model)
{
model.memberId = "Secret Id"
return View("MyView", model)
}
URL shows up as
http://localhost:1234/MyView?memberId=Secret Id
The data is not critically secret but having it show up in the URL is not really acceptable.
I don't know what you are up to, you should never set anything secret in a viewmodel - because the viewmodel is as the name says to be seen...
But to answer your question: To avoid the memberId occuring in the url you can submit your form by post - but that is of course not secure as well.
You should better store that in the session for example.
As already mentioned, view models are exactly that - models for your view. You should never store any data in a view model that should not be exposed to the client in one shape or form (whether it be a hidden form value, part of the url or in an ajax call).
If you really need data to be secret, and you want to pass it between actions, use TempData, or the ASPNet Session. That way, it goes nowhere near the client.
I wrote a CAPTCHA generator that uses TempData to store the actual CAPTCHA string, as sending it to the client would mean that any automated system would be able to read the string. I'd recommend using TempData over the session, though, as it's only persisted for one request - whereas the session needs managing by yourself.
TempData["MyDataIdentifier"] = "MyObjectOrValue";

When to use TempData vs Session in ASP.Net MVC

I am trying to get the hang of MVC framework so bear with me.
Right now, the only thing I'm using the session store for is storing the current logged in user. My website is simple. For this example, consider three domain objects, Person, Meeting, and File. Users can log in and view a "members only" profile of a meeting and can add files to it, or view a meeting's public "profile" if they aren't logged in.
So, from the meeting's private profile, with a logged in user, I have a "add files" link. This link routes to FileContoller.Add(int meetingId). From this action, I get the meeting the user want to add files to using the meeting id, but after the form is posted, I still need to know which meeting the user is adding files to. That's where my question lies, should I pass the "currently interacting with" meeting through TempData, or add it to the Session store?
This is how I currently have the Add action setup, but it's not working:
public ActionResult Add(int meetingId)
{
try
{
var meeting = _meetingsRepository.GetById(meetingId);
ViewData.Model = meeting;
TempData[TempDataKeys.CurrentMeeting] = meeting; /* add to tempdata here */
}
catch (Exception)
{
TempData[TempDataKeys.ErrorMessage] = "Unable to add files to this meeting.";
return RedirectToRoute("MeetingsIndex");
}
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(FormCollection form)
{
var member = Session[SessionStateKeys.Member] as Member;
var meeting = TempData[TempDataKeys.CurrentMeeting] as Meeting; /* meeting ends up null here */
if (member == null)
{
TempData[TempDataKeys.ErrorMessage] = "You must be logged in to add files to an meeting.";
return RedirectToRoute("LoginPage");
}
if (meeting == null)
{
TempData[TempDataKeys.ErrorMessage] = "An error occurred. No meeting selected.";
return RedirectToRoute("MeetingsIndex");
}
// add files to meeting
TempData[TempDataKeys.Notification] = "Successfully added.";
return RedirectToRoute("AddFiles", new {meetingId = meeting.MeetingId});
}
Edit:
Based on most of the answers, can any one provide any examples on what kind of data (other than messages) should be stored in TempData vs Session?
TempData is session, so they're not entirely different. However, the distinction is easy to understand, because TempData is for redirects, and redirects only. So when you set some message in TempData and then redirect, you are using TempData correctly.
However, using Session for any kind of security is extremely dangerous. Session and Membership are entirely separate in ASP.NET. You can "steal" sessions from other users, and yes, people do attack web sites this way. So if you want to selectively stop a post information based on whether a user is logged in, look at IsAuthenticated, and if you want to selectively show information based on what type of user is logged in, you use a Role provider. Because GETs can be cached, the only way to selectively allow access to an action in a GET is with AuthorizeAttribute.
Update In response to your edited question: You already have a good example of using TempData in your question, namely, returning a simple error message after a failed POST. In terms of what should be stored in Session (beyond "not much"), I just think of Session as a user-specific cache. Like the non-user-specific Cache, you should not put security-sensitive information there. But it's a good place to stick stuff which is relatively expensive to look up. For example, our Site.Master has the user's full name displayed on it. That is stored in a database, and we don't want to do a database query for it for every page we serve. (An installation of our application is used in a single company, so a user's full name is not considered "security-sensitive.") So if you think of Session as a cache which varies by a cookie which the user has, you won't be far wrong.
The default TempData provider uses the session so there really isn't much of a distinction, except that your TempData is cleared out at the end of the next request. You should use TempData when the data needs only to persist between two requests, preferably the second one being a redirect to avoid issues with other requests from the user -- from AJAX, for example -- deleting the data accidentally. If the data needs to persist longer than that, you should either repopulate the TempData or use the Session directly.
You can use it as per your requirement. A clarification can be,
TempData Vs Session
TempData
TempData allow us to persisting data for the duration of single subsequent request.
ASP.net MVC will automatically expire the value of tempdata once consecutive request returned the result (it means, it alive only till the target view is fully loaded).
It valid for only current and subsequent request only
TempData has Keep method to retention the value of TempData.
Example:
TempData.Keep(), TempData.Keep(“EmpName”)
TempData internally stored the value in to Session variable.
It is used to stored only one time messages like validation messages, error messages etc.
Session:
Session is able to store data much more long time, until user session is not expire.
Session will be expire after the session time out occurred.
It valid for all requests.
N/A
Session varible are stored in SessionStateItemCollection object (Which is exposed through the HttpContext.Session property of page).
It is used to stored long life data like user id, role id etc. which required throughout user session.
TempData and session, both required typecasting for getting data and check for null values to avoid run time exception.
"It doesn't work" isn't very descriptive, but let me offer a couple suggestions.
Under the hood, TempData uses Session to store values. So there isn't much difference in terms of storage mechanisms or anything like that. However, TempData only lasts until the next request is received.
If the user makes an ajax request in between form posts, TempData is gone. Any request whatsoever will clear TempData. So it's really only reliable when you're doing a manual redirect.
Why can't you just simply render the meeting ID to a hidden field in your View form? You're already adding it to the model. Alternately, add it to your route as a parameter.
I prefer to maintain that kind of data in the page itself. Render meetingID as a hidden input, so it gets submitted back to the controller. The controller handling the post can then feed that meeting ID back to whatever view will be rendered, so that the meetingID basically gets passed around as long as you need it.
It's kind of like the difference between storing a value in a global variable before calling a method that will operate on it, vs. passing the value directly to the method.
I would suggest MvcContrib's solution:
http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/
If you don't want full MvcContrib, the solution is only 1 method + 1 class that you can easily grab from MvcContrib sources.
The TempData property value is stored in session state. The value of TempData persists until it is read or until the session times out. If you want pass data one controller view to another controller view then you should use TempData.
Use Session when the data need for the throughout application

Resources