views:

190

answers:

4

I have been developing in classic ASP for about 2.5 years and I am trying to update my skill set to include ASP.NET MVC.

What is the MVC way of executing SSIs? IE: How can I include a database drawn navigation list in a sidebar? I have been looking into partial views, but they seem to get their content from the controller. As far as I can tell this means that I would need to write each controller to pass the navigation list.

Am I thinking along the right lines?

+1  A: 

Yes, partial views are the way to go. The controller should be handling the presentation logic. Similar to the code behind of web forms and web controls.

I would also utilize the master page for things like navigation.

Dustin Laine
thanks for the quick response! I've never used stack overflow before so i really appreciate the feedback.Just to clarify; if I want the same db drawn navigation on every page, then I need to write each and every control to grab that model for the partial view?The reason I ask for clarification is it seems (in my old-school way of thinking) that classic asp SSIs seem to be far less labor intesive.
Quakkels
As a former ASP programmer, you will have to break the thought process of ASP to ASP.NET. They are just too different. To alleviate adding a control to partial view to every view I highly recommend my second recommendation, using a master page. It gives you the navigation in a single place that can be included on every page.
Dustin Laine
+1  A: 

If I understand your question right and this is something you want to have an every page, RenderAction could be your friend.

chbu
Yes you understand my question correctly. RenderAction? cool... I'll go google that.
Quakkels
+4  A: 

You have two options that are similar to SSI

  1. Use either RenderAction or Action (explanation of the difference between the two)
  2. If you're using MVC2 there's also DisplayFor helper method which would allow you to define a custom display template for a particular object.

In your case Option 1 is probably the better one since you probably don't want to contain the items for the menu in your view model/view data.

R0MANARMY
Thanks, this makes sense.
Quakkels
+5  A: 

As an alternative to using RenderAction() (which has some drawbacks because it must run the entire ASP.NET request pipeline to get its output), you can use a BaseController type that all of your controllers inherit which overrides OnActionExecuted() to insert values into the ViewData collection. With this approach you will then have the benefit of using a single request, and still not having to worry about manually adding cross cutting data to your model every time you handle a request.

To keep things simple I like to use a public const string SomeDataItemViewDataKey = "Controller.DataName"; in the controller class definition to key the ViewData entry added by the controller and then in the view when I need to render that output I can use templated helpers to pull the value from the ViewData: <%=Html.DisplayFor(ControllerType.SomeDataItemViewDataKey, "PartialViewUsedToRenderTheData") %>.


Update

Because there's been some confusion about the validity of my statement, here is the original source of the performance claims against RenderAction():

Yes, there is a signficant difference in performance of RenderAction (slower) vs. RenderPartial (faster). RenderAction, by definition, has to run the whole ASP.NET pipeline to handle what appears to the system to be a new HTTP request, whereas RenderPartial is just adding extra content to an existing view.

-Brad Wilson, Senior developer on the ASP.NET MVC team

Quote source: http://forums.asp.net/p/1502235/3556774.aspx#3556590

Brad Wilson's blog: http://bradwilson.typepad.com/

Update 2

Here's the code from RenderAction() in the MVC2 RTM sources where we can see that although there is a new request being fired, it actually isn't going through the whole ASP.NET pipeline anymore. That being said, there are still some minor although mostly negligible drawbacks to using it over the alternative of PartialViews and ViewModel/ViewData. From what I understand (now) there was an overhaul on the implementation of RenderAction() prior to being moved from the MvcFutures assembly into the core framework; so it may hold that the statement above from Brad Wilson was more valid when he made it 6 months ago than it is now.

internal static void ActionHelper(HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, TextWriter textWriter) {
    if (htmlHelper == null) {
        throw new ArgumentNullException("htmlHelper");
    }
    if (String.IsNullOrEmpty(actionName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
    }

    routeValues = MergeDictionaries(routeValues, htmlHelper.ViewContext.RouteData.Values);
    routeValues["action"] = actionName;
    if (!String.IsNullOrEmpty(controllerName)) {
        routeValues["controller"] = controllerName;
    }

    bool usingAreas;
    VirtualPathData vpd = htmlHelper.RouteCollection.GetVirtualPathForArea(htmlHelper.ViewContext.RequestContext, null /* name */, routeValues, out usingAreas);
    if (vpd == null) {
        throw new InvalidOperationException(MvcResources.Common_NoRouteMatched);
    }

    if (usingAreas) {
        routeValues.Remove("area");
    }
    RouteData routeData = CreateRouteData(vpd.Route, routeValues, vpd.DataTokens, htmlHelper.ViewContext);
    HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext;
    RequestContext requestContext = new RequestContext(httpContext, routeData);
    ChildActionMvcHandler handler = new ChildActionMvcHandler(requestContext);
    httpContext.Server.Execute(HttpHandlerUtil.WrapForServerExecute(handler), textWriter, true /* preserveForm */);
}
Nathan Taylor
"(which has some drawback because it must run the entire ASP.NET request pipeline to get its output )" - This isn't true. RenderAction packages the existing request and starts a new MVC rendering lifecycle. RenderAction does not create a new Asp.net request pipeline.
jfar
@jfar If you'll note my updates, I have added the source of this *true* claim.
Nathan Taylor
Nice, I had the source for MVC preview 2 open instead of RTM when I looked at your claim. My mistake. Awesome that you followed up.
jfar