Html.RenderAction and Html.Action
One of the upcoming new features being added to ASP.NET MVC 2 Beta is a
little helper method called Html.RenderAction
and its counterpart,
Html.Action
. This has been a part of our ASP.NET MVC Futures library
for a while, but is now being added to the core product.
Both of these methods allow you to call into an action method from a
view and output the results of the action in place within the view. The
difference between the two is that Html.RenderAction
will render the
result directly to the Response (which is more efficient if the action
returns a large amount of HTML) whereas Html.Action
returns a string
with the result.
For the sake of brevity, I’ll use the term RenderAction
to refer to
both of these methods. Here’s a quick look at how you might use this
method. Suppose you have the following controller.
public class MyController {
public ActionResult Index() {
return View();
}
[ChildActionOnly]
public ActionResult Menu() {
var menu = GetMenuFromSomewhere();
return PartialView(menu);
}
}
The Menu action grabs the Menu model and returns a partial view with just the menu.
<%@ Control Inherits="System.Web.Mvc.ViewUserControl<Menu>" %>
<ul>
<% foreach(var item in Model.MenuItem) { %>
<li><%= item %></li>
<% } %>
</ul>
In your Index.aspx view, you can now call into the Menu
action to
display the menu:
<%@ Page %>
<html>
<head><title></title></head>
<body>
<%= Html.Action("Menu") %>
<h1>Welcome to the Index View</h1>
</body>
</html>
Notice that the Menu action is marked with a ChildActionOnlyAttribute
.
This attribute indicates that this action should not be callable
directly via the URL. It’s not required for an action to be callable via
RenderAction
.
We also added a new property to ControllerContext
named
IsChildAction
. This lets you know whether the action method is being
called via a RenderAction
call or via the URL.
This is used by some of our action filters which should do not get
called when applied to an action being called via RenderAction
such as
AuthorizeAttribute
and OutputCacheAttribute
.
Passing Values With RenderAction
Because these methods are being used to call action methods much like an
ASP.NET Request does, it’s possible to specify route values when calling
RenderAction
. What’s really cool about this is you can pass in complex
objects.
For example, suppose we want to supply the menu with some options. We
can define a new class, MenuOptions
like so.
public class MenuOptions {
public int Width { get; set; }
public int Height { get; set; }
}
Next, we’ll change the Menu
action method to accept this as a
parameter.
[ChildActionOnly]
public ActionResult Menu(MenuOptions options) {
return PartialView(options);
}
And now we can pass in menu options from our action call in the view
<%= Html.Action("Menu",
new { options = new MenuOptions { Width=400, Height=500} })%>
Cooperating with the ActionName attribute {.clear}
Another thing to note is that RenderAction
honors the ActionName
attribute when calling an action name. Thus if you annotate the action
like so.
[ChildActionOnly]
[ActionName("CoolMenu")]
public ActionResult Menu(MenuOptions options) {
return PartialView(options);
}
You’ll need to make sure to use “CoolMenu” as the action name and not
“Menu” when calling RenderAction
.
Cooperating With Output Caching
Note that in previous previews of the RenderAction
method, there was
an issue where calling RenderAction
to render an action method that
had the OutputCache
attribute would cause the whole view to be cached.
We fixed that issue by by changing the OutputCache
attribute to not
cache if it’s part of a child request.
If you want to output cache the portion of the page rendered by the call
to RenderAction
, you can use a technique I mentioned
here
where you place the call to RenderAction
in a ViewUserControl
which
has its OutputCache
directive set.
Summary
Let us know how this feature works for you. I think it could really help simplify some scenarios when composing a user interface from small parts.
Comments
57 responses