how to access session in view asp.net mvc - asp.net-mvc

I use MVC 3 with spark view engine. I have a data that should be accessed in every pages, the data base-on user login information. so I collect the data when user loged in and I put it on a session. I use a control to handle the data in site master ( master page ). and data in session will be binded to that control (eg. Dropdownlist ).
is it the best practise to handle data in master page on asp.net MVC ?
I try to create a base class for controller, buat I can't hold the login credential (HttpContext.User.Identity).
how can I access session data from View ?
I try to use #Session["mydata"] ( !{Session["mydata"] in spark view engine} but it didn't works :(
any helps ?

There are two general ways to handle this.
One is to use Html.RenderAction from your layout (master page). In that way you are packaging all of your data ahead of time into a model the master page will use.
The second way is to have your controllers inherit from another controller. When the base controller is instantiated, it is responsible for populating ViewData with the required data which is then displayed on the page. This requires all of your controllers to inherit from your base controller.
See listing 4/5 at:
http://www.asp.net/mvc/tutorials/passing-data-to-view-master-pages-cs
You could also do this via an action filter (and other ways too!!) but I think the above two ways are a bit cleaner

You should be able to get to the credential of the logged on user by calling System.Threading.Thread.CurrentPrincipal.Identity.Name in your controller base class.
That should allow you to populate the ViewData and then access the data from your view.
Alternatively if you still want to use the session, you should be able to access the session via - HttpContext.Current.Session["mydata"]

you can use TempData["name"] for sharing data on different actions in a controller. Remember once value is retrieved, it will delete the data but you can use .Peek and .Keep method functionality to store its value

Related

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/

Passing data from controller superclass to view?

I'm writing an Asp.net MVC application (my first MVC app). I need to pass data to the _Layout view to customize the header and footer on my pages - which user is logged in, if they have any notifications, etc. The _Layout page always needs this information, but the child pages do not.
How should I pass this data to the view? Can I create a LoggedInUser property that the view can access, in the same way there is a Model and ViewBag? LoggedInUser could be populated by the base controller class.
Or is there a better way to implement this?
If you're using MembershipProvider and/or RoleProvider you can do as webdeveloper pointed out to get the identity of the current user User.Identity.Name, if showing it's name is what you want.
Also you could type your _layout to use a specific model, but I don't recommend it. See this question's answer for further details.
Lastly you could populate a ViewBag property on your controllers to have the user information you need.
I wanted to point out that you could do a partial view to achieve this, and avoid _layout typing and populating the ViewBag on each request.
To detect authentication:
User.Identity.IsAuthenticated
Then you can use sections ASP.NET MVC 3: Layouts and Sections with Razor or/and #Html.RenderAction (Html.RenderAction and Html.Action)

Code behind user control

How would one go about performing controller actions from withing an ASP.net MVC user control?
My scenario is that I have a userID and I want to transform it into a name from the database. To do this I've annotated my model with a display type and put a User template in the shared display templates but I'm not sure where I should write the code which does the lookup to convert from userID to user name.
I think that code ought to go into your models and you should be calling it in your controller and passing it to your user-control in a viewdata. This is if I understood your question.
I would just have the model expose the name and not the userID. This way your view (user control) is only displaying the name and not trying to do a DB lookup. Your "User Control" model would be responsible for how it gets the name, i.e. the DB from your question.
In short, you don't do that.
You should be passing the necessary data to the MVC user control from the View, which in turn should be getting it's information from the controller.
The view (or user control) should not have any knowledge of the controller. You may want to use RenderAction instead of a user control if you feel that the view shouldn't be responsible for passing the necessary information into the user control.

Providing data to Menu in my ASP.NET MVC Master Page

We are beginning the process of moving from Web Forms to MVC for all of our new applications. I am working on porting our Master Page over and am trying to satisfy the requirements that we need a single master page to be used by all applications. The primary navigation for the application needs to be in a menu within the master page. Accomplishing this was easy, the hard part is that each application may need to determine what to display in the menu using a unique set of rules. Some apps can simply say, here's the menu structure to use via something like a SiteMap. Others need to determine what is displayed in the menu based on what roles the user has, this can also be handled easily with a SiteMap. The situation that I'm struggling with is that some apps need to generate the menus based on the roles the user has, but also on the data on which they are working. i.e. The same user may have different option in the menu for a page if they are working on object 'foo' than they do if working on object 'bar'.
What I've done at this point, is I've created an HtmlHelper that is called by the master page view and takes a list of objects of a custom type and returns an unordered list that is styled by a jQuery plugin to display the menu. The list of objects the helper method takes are passed to the view using the ViewData dictionary. Currently, the value of this ViewData node is set within the constructor of each controller. This allows each page, and potentially each method, to set a different menu without having to set the value in each action method, unless its needed. I have also created a class that parses a SiteMap and returns the list of items needed to build the menu. This class is what I'm using to set the ViewData value in the controller. The idea being that if an application needed more control of how the menu data was generated, they could create their own class to generate the data as long as it returns a list of the correct type of objects.
This solution seems to work fine so far, it just doesn't 'feel' right for some reason. I'm hoping that I can either get some ideas of better way to do this or some reassurance that this is a valid approach to solving this problem.
If it is something that will be on every page, do something like this:
Create a base controller:
public class MyBaseController : Controller
Have this controller get the data it needs and send that data in the ViewData["menu"] to the View. Then have all your controllers inherit from this one:
public class HomeController : MyBaseController
In the Master Page, loop through your ViewData and create your menu.
(I did something like this for my sub-menu which displayed a list of categories.)
In the book I am reading (Pro ASP.NET MVC Framework by Apress) they use Html.RenderAction for the menu in the masterpage. I am a Asp.net MVC novice so maybe somebody else can give more info about this.
You can download the sourcecode at apress.com though so maybe that could help.

ASP.Net MVC & Memberships

I would really appreciate some feedback on what I am trying to achieve:
The problem:
I would like to authorize a user of my application to a single action on the controller. For e.g.: a user can perform the "save" action on my controller class if he has the required authorization.
In the project I am working on, the creation of roles & their authorization is done by the client deployment team & not in my control. So, I program to a "control point" which can be assigned to role/user, while my application needs to only check that control point.
How do I get a control point concept into ASP.Net MVC? More specifically, how do I enable/disable buttons on the View based on the user permission on the controller?
My solution:
Ref.: http://weblogs.asp.net/fredriknormen/archive/2008/03/12/asp-net-mvc-framework-2-interception-and-creating-a-role-action-filter.aspx - as a starting point
Instead of creating a role filter as explained in the link above, I would have a ControlPointFilter class which would get the model & do the authorization check.
The trouble I have is in the View class & I am currently passing the control point collection to which the user has access in the ViewData[] collection.
In the View class, I am checking if the related control point is present in the ViewData collection (which I don't like - want to keep the code to a minimum in the View class)
The other issue is - while the actual control point name is being set in the attribute to the controller class, where/how can I pass these attributes to the view & yet keep the view clean?
Hope that helps & appreciate your time/effort to answer this!
Sunny
One possible solution to this is to translate control points into view attributes in your controller actions (perhaps these are the same things, though, it's not clear from your question). The idea would be that your control point would translate into meaningful view directions such as "AllowEdit", "AllowSave", "AllowDetailedView", etc. These would become entries in ViewData.
Use a base controller class to extend Controller and give it a ControlPoint collection. Have your filter populate this collection in the controller. Have the base controller OnActionExecuted method use this collection and, in the case of a ViewResult, populate the ViewData with the appropriate values for the collection of view directives. Individual controller actions could also use the ControlPoint collection to determine whether they need to provide data for individual views based on whether the view will render extra data or not.
In your view, rely not on the control points themselves but the view directions determined by the base controller. This way you've decoupled the views from the control point logic. Views only operate on view data in ways that are meaningful to the view, not on permission-based data that have meaning in the context of the application. The view won't care how or why the particular directive gets set, it only needs to render appropriately based on the value of the directive.
Hmm, could you not simply create a templating system, to assign roles to users? I.e. create a user template "Power User" that has the roles "CustomerService" and "ConfigurationEditor", and then use the role system as pr usual (i.e. Roles.IsUserInRole(username, rolename))?
For actions, you then use
[Authorized(Roles="CustomerService,CustomerServiceAdmin")]
public ActionResult Edit(...)
{
}
For views, you use
<% if (Roles.IsUserInRole(Context.User.Name, "CustomerService")) %>

Resources