Is it a good practice to access session data in view? - asp.net

Which is better from design and coding point of view: accessing session data in the view directly or loading them in the controller and passing them to the view using a viewbag?

MVC wont really care if you do something in your controller or your views but i agree with shaftpolls for not hurting the mvc pattern. Since Session is already inside the ViewData wrapper, you can access it directly in the View.
Be aware, that the Session object should only contain simple, non-sensitive data like user picked language, or custom ui-colorsheme.

If you really need to use Session, you should get that data on the server side and then pass it to the View using Strongly Typed properties in a View Model rather than using the ViewBag.
So let's say you have a property on your view model which is of type IENumerable<SelectListItem> and inside your view you will use the strongly typed version of the Html.DropDownListFor helper to bind to the model this way:
#Html.DropDownListFor(x => x.ProductId, Model.Products)

The best thing to do is access the session in the controller. Why:
Performance. You have fine control of how to access the Session object. If you need to read just properties of the session, then specify that you need read-only access to the session, MVC won't block the session, you'll get more performance.
Pureness. In a pure MVC scenario, the view knows only about the model. So any value that you care about in your session must be passed as part of the model.

Related

ASP.NET MVC objects lost on post method

I just came across this topic in a current project and I would like to know the best way to handle the "problem" of objects getting lost, when using the HttpPost method when submitting a form. Thoughout the web and the posts on stackoverflow I gathered some ways to deal with it.
So, once I got that a view model gets objects or lists from the HttpGet request they are lost because of the stateless nature of http. I now have seen different approaches to get that objects back when passing the view model back to the view.
Store objects in hidden field
#Html.HiddenFor(m => m.Object)
This seems to be working fine if the view models property is serializable. But what if there is logic behind the objects? Will this work for all scenarios? And on the other hand, I don't want every object inside my view model, just the ones for display and the user can interact with.
Get the object via AJAX and HelperMethods
#Html.Some3rdParty().ComboBoxFor(m => m.List)
.DataSourceUrl(#Url.Action("GetComboSource"))
[ComboBoxSource]
public ActionResult GetComboSource()
{
var data = Service.GetStaticSource();
return Json(data);
}
Using 3rd party libraries like Kendo UI MVC I can easily put a .DataSourceUrl() HtmlHelper on my control for requesting a controller to provide the datasource. Or just using jQuery's $.get() method. The problem is: What if I can't use such a library or the requirement says, that JS has to be avoided as much as possible?
Get the object back in the HttpPost Controller action
[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
var tempViewModel = Service.GetViewModel(viewModel.Id);
viewModel.Object = tempViewModel.Object;
return View(viewModel);
}
This one seems a bit brittle to me. On the post action I have to call whatever service provides the view model, extract certain objects and attach them to my recieved view model.
Currently that's all I can think of, but in short:
I'd like to know, what is the best practise to handle it throughout a project and what's the best way for maintainability?
For me it seems there is no perfect solution so far. How do you do it in your projects?
Avoid solution 1: you will weigh your requests, the data can be forged and if your object is not serializable (or the to string method does not provide useful string) you will have some problems. If you want to use something similar prefer Session
Solution 2: I use ajax populating when the input have to be filtered depending of other controls value. If it is not the case you will have controller with lot of actions and not easily maintanable.
Solution 3 is the one I use and I prefer because it is more DRY, more secure (no forgery), and keeps the controller light.
Just change
<input class="ui-input-text " type="text" id="PlateNo" tabindex="2" name="PlateNo">
to
<input class="ui-input-text " type="text" id="PlateNo" tabindex="2" name="PlateNo" value="#Request["PlateNo"]">
You can be show on the textbox sending value for this input.
Only add value="#Request["yourinputname"] to your input.

In ASP.NET MVC, Data exchange between Model and View is possible?

Is there a option to pass data between Model and view in ASP.NET. If it can be accomplished how? This was asked in an interview !!!
Yes... well, the view is either typed, which means the object that represents the model is directly accessible, or the controller returns a ViewBag with data or anything else the view needs to render. That's the whole point of the model-view part of the pattern.
The whole point of MVC is that the data(Model) should be shown to user (View) by use of Controller. Even if the view is typed, your still need the model to bind to it. Even to create a ViewBag, you need the controller action to fill it...

asp.net mvc3 / razor view best practices

I am using in my views (asp mvc3/razor cshtml) references to the Request object (eg, #Request.Params["Name"]). Do you think this is a very bad practice? Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Best practice is to use a model class. An instance of the model class is created or updated in your controller. Then the controller displays a strongly-typed view.
So I'd avoid direct access to the request from the view as well as the use of the view bag.
Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Yes. You will avoid runtime errors if "Name" does not exist.
The IDE will not warn you of the NullReferenceException about to be thrown with the following code.
#Request.Params["Fake"].ToString()
Of course, you'll have to be careful about ViewBag.Fake being null as well.
I like to use the viewbag to store things not related to the model, for example if I have a dropdown containing locations. I like to store only the id of the selected location on the model and the locations in the viewbag, since is not needed to create a contact. I think that's the purpose of the viewbag.
For me the model is a bag or properties used in business operations, for example if I have a customer creation view using a NewCustomerModel, I don't wanna pollute my model with things like a IList<CustomerType> AND a SelectedCustomerTypeId property. I just want the second since is the one imma use to create the customer.

Calling cached data (in service layer) from an ASP.NET MVC View - what other alternative do we have?

We are adding tooltips to our ASP.NET MVC product, and we are getting the text from our database (technically, from a cached copy of the data). To do so, we created an Html Helper method:
<%=Html.Tooltip(Model.GetTooltipText(Tooltips.ClientPage.StartDateId))%>
The GetTooltipText method is in our BaseViewModel, and simply uses the passed in Id to fetch the tooltip from cache.
Would this be considered a bad design? What other alternatives would we have?
Thanks!
Its probably a better idea to grab all the Tooltip's in one hit and put them in some sort of strongly-typed collection (perhaps a Dictionary<id,string>), cache all of that in your service layer.
Then you could put this in a ViewModel and pass it through to your strongly-typed view.
In your View you could simply access that strongly-typed collected via the Model based on the unique key?
I.e.
<%: Model.Tooltips[SomeDateId] %>

How do you decide on the means of passing model data from asp.net mvc controllers to views?

There seem to be multiple means of passing model data from controllers in asp.net mvc to views. Its not clear to me if there's a recommended approach in the mvc v1 and v2 releases or if like most things in life, it depends. I've seen several approaches:
Option 1 - Populate the controller's ViewData dixtionary in either an icky string-based indexing way with casting in the view, or the in a strongly typed way by creating a strongly typed custom model class and passing that via ViewData.
Option 2 - Use ViewData.Model, which I'm not sure I even understand.
Option 3 - Use ViewPage.Model, in which case I'm not sure how you pass the model data from the controller.
I've seen a number of posts poo-pooing options 1 and 2 but I don't understand why. These posts seem to highly recommend 3 in most cases.
How do you approach this? Is there a standard way?
Every view 'should' have a specific model. This is sometimes more work so people use short cuts like ViewData, which works but is just not as clean and type safe in my opinion, so I prefer to have everything in the view's model.
You can then make all your views stongly typed. This is a very clean way to do so. Then in your controller you just call the view like:
YourViewModel model = new YourViewModel()
{
// initialize the data here
};
View(model);
Then in your views you can access all the data via ViewPage Model and it is all type safe and enforced from the controller as well.
EDIT from comments:
You don't need to use ViewData at all if you don't want. You can encapsulate all the data your view needs in a model. Just like the example you quoted with ProductsListViewData. It's just a model that contains all the items that were going to be stored in the ViewData. Both ways work but when you encapsulate it in a class (preferred method where everything is in the model) then all the bits and pieces are strongly typed.
ViewData is a generic container so even though you can just put anything you want into it, it is not type safe and therefore not as 'clean'. It comes down to preference and maintainability. There is only option 1 and 3. Your option 2 is misunderstood and is just option 3 in reality. There is no ViewData.Model just ViewPage.Model.
One approach you may wish to consider as your views become more complex, is to reserve the use of Models for input fields, and use ViewData to support anything else the View needs to render.
There are at least a couple of arguments to support this:
You have a master-page that requires some data to be present (e.g. something like the StackOverflow user information in the header). Applying a site-wide ActionFilter makes it easy to populate this information in ViewData after every action. To put it in model would require that every other Model in the site then inherit from a base Model (this may not seem bad initially, but it can become complicated quickly).
When you are validating a posted form, if there are validation errors you are probably going to want to rebind the model (with the invalid fields) back to the view and display validation messages. This is fine, as data in input fields is posted back and will be bound to the model, but what about any other data your view requires to be re-populated? (e.g. drop-down list values, information messages, etc) These will not be posted back, and it can become messy re-populating these onto the model "around" the posted-back input values. It is often simpler to have a method which populates the ViewData with the..view data.
In my experience I have found this approach works well.
And, in MVC3, the dynamic ViewModels means no more string-indexing!
This might be of some help:
When is it right to use ViewData instead of ViewModels?
(I know the following answer is highly arguable, but it's just the way I like to do it)
I would say use ViewData for simple data-tasks, and use the Model for the main purpose of the View. Check out Rob Conerys ViewData helper-classes here to give them a bit more Strongly typed feel:
http://blog.wekeroad.com/2010/01/20/my-favorite-helpers-for-aspnet-mvc
Using Models for absolubtely everything will bloat your project with hundreds of models just to achieve the smallest thing. I mean if you have a User-setting page, you would normally pass a User-model into the view, but if you decide to show some related data like Customers related to this User. You're stuck with the following solutions
You might have to add a List property to the User-model in order to expose the customers to the view. This leads to the Customer-property always being applied to the User-model everywhere else in the project - or make a new simpler User-model.
Make a new action that returns a partial of customers, which you can use with Html.RenderAction.
OR
you could do ViewData["Customers"] = myRepo.GetCustomersRelatedTo(user); // or something like that.
and (if using Robs helpers) in your view:
<%= Html.RenderPartial("CustomerList", Html.ViewData("Customers")) %>
add a PartialView called CustomerList that takes IEnumerable
In my humble opinion this is a cleaner solution and sure - you end up with a magic string here and there, but I'll stick to this approach until someone shows me a project with not a single magic string.
Use the tools we have in the Framework to get the job done. and Keep it simple s... ;)

Resources