开发者

ASP.NET MVC Master Page Data

The more I use ASP.NET MVC, the more I love it. However, in the case of showing model data on master pages there seems several ways of doing it. I am unsure as to the best solution.

My example would be a commerce site where I want to output a list of product categories on every page and also show the status of the visitors cart.

In asp.net web forms I would typically do this using user controls each doing their own databinding to retrieve the required data.

In MVC all data should be passed by the controller.

So regarding the categories the simplest solution would seem to be to pass this in View data in the controller action:

ViewData["Categories"] = _service.GetCategories();

However, doing this for every action isn't very DRY so following this article I created a base controller that adds the required data to my ViewData:

    public class AppController : Controller
{
    IAppService _service;

    public AppController() { }
    public AppController(IAppService appService)
    {
        _service = appService;
        SetSiteData();
    }

    private void SetSiteData()
    {
        ViewData["Categories开发者_运维知识库"] = _service.GetCategories();
    }
}

I then created an extension for ViewMasterPage:

        public static void RenderCategoryList(this ViewMasterPage pg) {
        pg.Html.RenderPartial("CategoryList", pg.ViewData["Categories"]);
    }

And in my MasterPage:

        <div>
        <%this.RenderCategoryList(); %>
    </div>

This seems quite a clean approach. However, is this the best way as I have also seen suggestions of creating a ViewModel for your MasterPage. I could see that perhaps as your ViewModel data grows, this may be a better solution.

Regarding the cart status, I suppose I would do something similar but am unsure whether RenderAction would be more appropriate (When to use RenderAction vs RenderPartial with ASP.NET MVC). Thanks, Ben


That works, although it's not the way I would do it for 2 reasons:

  1. I don't like sticking data into ViewState since you essentially cast it as object
  2. By requiring a base controller you're limiting the functionality to controllers that inherit from this basecontroller (which might not be an issue though)

I think this would be a perfect use of RenderAction (part of the MvcFutures project). This helper can be used to render an Action on another controller. So you might have a ProductController with a ListCategories action, you could just do something like:

<% Html.RenderAction<ProductController>(x => x.ListCategories()); %>

ListCategories would call

_service.GetCategories();

and might stick the info into its own Model. Then it would pass that model to the View would would be a Partial Page.


Thank you - RenderAction was perfect the job.

I got more information from here.

So for the benefit of others, here is an example of how I am outputting cart status:

Action:

    [ChildActionOnly]
    public ActionResult CartStatus()
    {
        return PartialView(_service.GetCartSummary());
    }

Partial View (bound to Models.Cart)

<div class="cartSummary">
<%if (Model.HasItems) { %>
    Cart Items: <%=Model.Items.Count() %> | Total: <%=Model.TotalItems %>
<%} else {%>
    Your cart is empty. Please buy stuff!
<%} %>

Helper method for Master Page:

    public static void RenderCartStatus(this ViewMasterPage pg) {
        pg.Html.RenderAction("CartStatus", "Catalog", null);
    }

And finally master page:

<%this.RenderCartStatus(); %>

Thank you for the advice.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜