Accessing session data from a layout - asp.net-mvc

In my ASP.NET MVC solution I have a number of services.
One of them, SessionService, is used to access the currently selected region and time span.
I want to display those in a layout used to decorate views. What is the best design approach to access those values which are stored in the SessionService?
Right now I'm thinking about using calling a ChildAction from the layout which in turn calls the session service:
_Layout -> aController.ChildAction() -> SessionService.GetRegion()
Is it a good approach or can you recommend anything better?
UPDATE 1:
Other options for passing the values that are possible:
via ViewBag
via ViewModels
However the drawback for these options is the fact that it would be necessary to populate them in each and every action method which would lead to duplication of code (which could be mitigated by means of a filter, but again this will require decorating controllers with the filter).
UPDATE 2 (born in the discussion with O:rvar below):
Another option is to create a base controller which will be populating ViewBag properties upon creation. All other controllers should derive from it.

You should be able to access you session data in the view with the following code:
var region = #Session["Region"].ToString();
Or you could call the controller method as you mentioned with an ajax call and get the session data that way. Using the childaction approach is also a fine way of accomplishing what you want.

Related

MVC embed data in Master Layout without violating standards

I have a master layout for a conference registration system, what I'm trying to do is to display the number of registered users in the master layout.
What is the best way to do that ?
I can call a static method to get this count, but from my knowledge, this is a violation of the MVC standards, because interaction between a page and the server should be only through Controller/Action method.
So what is the best way to do this ?
When I need to display data in the layout page, particularly if it's a small amount of data, I usually put that data into ViewBag/ViewData. Otherwise you need a base class model that every developer has to remember to inherit from to carry the data into the view. The ViewBag/ViewData can then be populated by an OnResultExecuting filter on the base controller class.
You need to have main Model/ViewModel for all of your pages or use two or multiple Models/ViewModel in targeted pages. In this way you pass all required data to view via controller methods perhaps by calling a static method in methods. see the following articles to employ the above techniques:
Two models in one view in ASP MVC 3
Multiple models in a view
Another way is storing related data in ViewBag or ViewData Dynamic types in controller methods each time needed and then prepare and use them in View. Note that using them should be avoided in favor of using strongly typed ViewModels.
cheers.

Display & Update Cart Count on an MVC Layout Menu

I have an MVC application which is supposed to show a Shopping Cart Count on the primary _Layout page. I need to update this value as users add or remove data from their cart. Since these data changes can be done from multiple locations throughout the application, I'm hesitant about putting GetCartCount() calls on each and every controller out there.
I was considering using either a ViewBag or a knockout computed observable to store this value in, but I'm open to any other suggestions.
What is the best way to store & update a single value that will be used on a layout page in an MVC application?
The simplest way would be to put this count variable in the Session and output it directly inside of the _Layout.cshtml using #Session. If you don't want to use session you can put this count variable in the ViewBag with every request, you can set it in the BaseController(if you don't have one just create one and inherit your controllers from it) in OnActionExecuting method and you will avoid duplication.

Synthesize multiple action methods in MVC

We have a dashboard-style application with lots of individual bits of the screen that load asynchronously. Each of these bits really makes sense as its own action on the page's controller. However, the data will load more quickly if we reduce the number of http requests to 1. I'm considering creating an action that just returns a combination of results from several smaller actions, such that the web client can GET the actions separately or together. However, this seems like a hand-rolled solution to a common problem, so I'm wondering if there's built-in support for agglomerating actions in this way that I don't know about. Anybody?
In your core view, you can use the Html.RenderAction() method to render completely separate actions from another action.
Why don't you just use ViewModel containing all data needed for your dashboard and then create several partial views, feed them with data from ViewModel?
I have also an dashboard in my project, I did it this way and I am happy with the solution. I have DashboardController and its Index action just takes ViewModel (which aggregates all necesary data) and sends it to View. In that View, I have several partial views (each of them needs its own model) and I pass them data from my ViewModel. Inside that partial view are then references to specific actions (like CRUD for specific models).
When you do it this way, you can easily create partial views for specific models (Task, Project, User .. in my case). And then just use them as a pieces in your final layout. My ViewModel contains collections of Tasks, Projects and Users which I then simply pass to matching partial views.

Rendering Navigation in MVC3

What's the best way to render Navigation in MVC3? In my app the Controller has to decide what should be in the Navigation but as far as I know there's no way to pass a Model up to the _Layout file (where the Navigation html lives) to give it this information.
You can make the model available to your layout.
Define a base class, MyBaseModel, with the properties you want available to the layout.
Have your models subclass MyBaseModel, and ensure that you populate the properties
Have your layout specify #model MyBaseModel
Use the properties
See also this blog post where a similar problem ("we often find ourselves needing to include the same information in every page") is tackled.
Best is a relative and subjective term. I would usually go with an approach similar to druttka's answer but another option is to use RenderAction() to invoke a controller action
<div>#Html.RenderAction("action", "controller")</div>
I will offer some counterpoints to #druttka's answer. But mostly, you have to decide which trade off you want to make.
If you use a model for your view, you are now forcing 2 things:
Every view must be strongly typed
Every action must call the function to populate all levels of nav included in your view model
The first point isn't so bad, because there are very few pages in a typical non-static site which wouldn't derive from a model anyway, and its easy enough to create an empty model for those pages. The second point is much more annoying however. Each function has to instantiate it's own model, and then populate the nav properties for every level of nav provided by the model. This can be quite cumbersome, but can be fairly elegantly handled in OnActionExecuted for at least nav which is not specific to a given action.
The alternative is to add the nav to the ViewBag. This can be done whenever and does not force you to specify a model for every view, which is great for the flexibility in those cases where you do not need to specify a model. It should be noted however that the ViewBag in asp.net mvc 3 is of type dynamic, which you cannot use as a parameter in a lambda function, thus preventing you from doing something like #Html.DisplayFor(viewBag => viewBag.MainNav) in your layout, which is a real drag. You can still render partial and specify the appropriate DisplayTemplate however.

Can I use a MVC Global Action Filter to disable form fields?

Some users of our application will have read-only access to many of our pages, in our current web forms app this means they see the form, but all of the fields are disabled. We're looking at MVC 3 and searching for the cleanest, most idiomatic way of implementing this functionality.
Some ideas so far:
Some combination of a global action filter and edit templates.
A custom Html helper, something like Html.SecureTextBox etc...
I'm leaning towards number 1, but I'm wondering if any of you guys/gals with more MVC experience have solved this problem in a better way.
I agree with using a base view model, or perhaps just an interface with a "CanEdit" type of property. If you go the interface route, you could set the property in an ActionFilter in the OnActionExecuted method.
To tie it to the view, creating a new HtmlHelper would be pretty easy. I'd use TextBoxFor as the base class, since it has access to the view's model. You can then inspect the property and create the necessary HTML attribute. However, with going this route you will need to create a new helper for each type of input control you need (textbox, select list, etc).
Without knowing all the details of what you are doing, a much simpler idea would be to not provide a Save button for read-only users. The Save button would be driven by one property in the view model (or ViewData, if you like).
Several other people mentioned that a server-side restriction is still needed to prevent people from bypassing the client-restrictions. You will need an action filter for this. This link has a good idea about that.
My preference would be to set a variable in a common base view model (or ViewData), using a global action filter, and then use a bit of jquery to dynamically disable the input fields, delete buttons etc.
$(':input').attr('readonly', true);

Resources