An HtmlHelper that I have been enjoying in the ASP.NET MVC 1.0 Future’s Assembly is Html.RenderAction. Briefly, Html.RenderAction allows one to call a controller action from within an ASP.NET MVC View and write the output of the action directly to the Response Stream.
Putting aside the controversy of calling a controller action from within a view, RenderAction offers a simple solution to filling in those parts of a view that are not directly related to the request itself. If a visitor to your website is requesting to see a particular product from your product catalog, allow the request to just focus on getting the product and passing it to the view. Leave other cross-cutting concerns, like displaying the list of categories on the same page, to Html.RenderAction in the Master Page or View.
Changes in ASP.NET MVC 2 Beta
With ASP.NET MVC 2, which will be included in Visual Studio 2010, Html.RenderAction has now been included in the core ASP.NET MVC Assembly as well as it’s brother, Html.Action. Where Html.RenderAction writes directly to the Response Stream, Html.Action returns a string.
Html.Action – Outputs String
<%= Html.Action("NavigationSideBar","Categories") %>
Html.RenderAction – Renders Directly to Response
<% Html.RenderAction("NavigationSideBar","Categories"); %>
My take on choosing one over the other at the moment is purely based on performance. Writing directly to the Response Stream is better performing, so if you are dealing with large amounts of data you probably want to choose Html.RenderAction. If it is a small amount of data or you want to capture the output for some reason before sending it to the browser, Html.Action can be used.
ChildActionOnlyAttribute - [ChildActionOnly]
An interesting change in ASP.NET MVC 2 is the addition of a ChildActionOnlyAttribute, which specifies that an action on a controller is only to be called from within a View and NOT from the outside. Therefore if an action on a controller is only to display a navigation bar on a page, for example, decorate it with the ChildActionOnly Attribute so that it can only be accessed from the View.
[ChildActionOnly]
public ActionResult NavigationSidebar()
{
return PartialView(_catalog.FetchCategories());
}
Any attempt to call an action decorated with an attribute from the outside will cause an exception – “The action 'NavigationSideBar' is accessible only by a child request.”
ControllerContext.IsChildAction
In coordination with this concept of Child Actions, Microsoft also added a property on the ControllerContext Class, called IsChildAction, so that you can determine if a request is a Child Action. This may certainly prove useful in ActionFilters, for example, where you may not want to perform certain actions when a request is a Child Action.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.IsChildAction)
{
// ...
}
}
Conclusion
I would take some time to consider if Html.RenderAction and Html.Action are for you. Some developers prefer that Views do not call into Controllers, which gets back to the purity of Model-View-Controller as well as avoids all the “complexity” offered by ControllerContext.IsChildAction and [ChildActionOnly] attributes. Certainly these changes do have a “hackish” feel to them.
An alternative is to use ActionFilters for cross-cutting concerns. This is out-of-scope for this blog post and is certainly not without its own issues.

Comments