views:

250

answers:

3

I am loving MVC but can't see to understand how your meant to implement User Controls. If I have a Multiple views each with shopping basket details how can I encapulate the shopping basket view and code so I don't have to return the basket data with each controller viewdata?

+4  A: 

From this MSDN page:

A partial view enables you to define a view that will be rendered inside a parent view. Partial views are implemented as ASP.NET user controls (.ascx).

Write out your shopping cart view in a partial view. Within a ViewPage, you call Html.RenderPartial("PartialNameHere") to render this to whatever spot on the page you called it from. Like views, you can have strongly-typed Partial Views so that you can pass in a Model of whatever type you choose.

Please note the following (also from the MSDN link above; emphasis mine):

When a partial view is instantiated, it gets its own copy of the ViewDataDictionary object that is available to the parent view. The partial view therefore has access to the data of the parent view. However, if the partial view updates the data, those updates affect only the partial view's ViewData object. The parent view's data is not changed.

Andrew Song
+1  A: 

You have to return basket data in each controller action that will return the view that use the basket user controll. But there are methods to avoid code repetition here. You can decorate the action method with custom ActionFilterAttribute that will inject the appropriate data in OnAxctionExecuted event, or you can add basket data to ViewData dictionary in base controller Initialize method and then access it in control with ViewData["magic-string"] or create extension method on HtmlHelper to avoid magic strings.

PanJanek
I would not suggest relying heavily on magic strings. They are rife with issues. Strongly typing is preferable and then makes the partial view easier to implement as well.
Anthony Potts
I agree. It was just one of many options. The best solution is to create base model class for all view models and place data used by user controls there. Then, after populating the data in ActionFilterAttribute, one can pass specific data to user control in the view with Html.RenderPartial("MyControl", Model.MyControlModelFromBaseViewModel).
PanJanek
just to get thing clear: if I choose to pass cart data in every controller action, what is the best way to implement this? Inherit every View Model class from a base which will store cart data? Is so, it seems to be a very limiting rule, maybe ViewData is more suitable for this?
kilonet
I think ViewData can be used for that, but you shouldn't access it by ViewData[] in views (because it's messy) but write an extension method on HtmlHelper or MvcView class for getting it. More important is where to initialize the model with cart data - custom ActionFilterAttribute is handy.
PanJanek
+2  A: 

The other answers are exactly right, but there is a second option. You could render your partial view as a result of an AJAX call to a controller action dedicated to your partial view. That way your partial view just has to deal with a model that has data only it cares about.

Arthur C
I agree that it is most elegant solution from the perspective of the project architecture. I was many times tempted for this kind of solution, but the standard problem is "What if user has ajax/js disabled?" Some core functionality (like shopping basket) will be inaccesible. The second drawback is that getting part of the page in another ajax request slows down loading of the page and affects users experience - the page looks less responsive.
PanJanek
Well I agree slightly. If you have too much coming down (either large volumes of data in a single call, or many smaller ajax calls) it can slow down your page, but if you use it wisely it works great. Like everything in life, use it in moderation.Regarding ajax/js disabled. Honestly I don't worry about that too much these days. It was definitely a problem maybe 5 years ago or so, but I haven't run into a problem with a client disabled js. That doesn't mean it doesn't exist, but its definitely not as common as it used to be.
Arthur C
the mean reason to not use ajax call is for seo where the js isn't ran
monkeylee