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开发者_如何学JAVA 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?
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 */);
}
You have two options that are similar to SSI
- Use either RenderAction or Action (explanation of the difference between the two)
- 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.
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.
If I understand your question right and this is something you want to have an every page, RenderAction could be your friend.
精彩评论