Html.RenderAction and Html.Action

0 comments suggest edit

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();
  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>" %>
<% foreach(var item in Model.MenuItem) { %>
  <li><%= item %></li>
<% } %>

In your Index.aspx view, you can now call into the Menu action to display the menu:

<%@ Page %>
  <%= Html.Action("Menu") %>
  <h1>Welcome to the Index View</h1>

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.

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.

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.


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.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.



56 responses

  1. Avatar for Kazi Manzur Rashid
    Kazi Manzur Rashid November 17th, 2009

    Excellent, a long awaited features that gets included in the core. So the parent action filters does not get executed in this version?

  2. Avatar for Steve
    Steve November 18th, 2009

    One more suggestion, and admittedly this doesn't come from someone who's using ASP.NET MVC right now, so there might already be a way to do this. But it overlaps with some work I've been doing on a different framework so I thought I'd mention it...
    Since you already have a good typeless URL -> typed parameter parser, why not allow the passing of options as an URL string? In other words,
    <%= Html.Action("Menu", "width=400&height=500") %>
    This allows you to create composable subparts without the burden of strict typing, for instance:
    <%= Html.Action("Menu", "width=" + Request.Params["menu.width"] + "&height=" + Request.Params["menu.height"]) %>
    That in turn could have a params-based wrapper so that it could be written as <%= Html.Action("Menu", Passthru("width","height")) %>
    The end result is that you don't need to use endless generic wrappers to do simple operations - on data that began its life as a generic string anyway.
    In general I'd love to see more of this, where mvc takes on the strengths of dynamic templating languages like PHP, with the power of typed actions when you need them.

  3. Avatar for Jeffrey Palermo
    Jeffrey Palermo November 18th, 2009

    Very cool to include it in the core product. I really like Html.Action() as well. Good job, Phil. Keep up the great work. You are changing the world of ASP.NET development!

  4. Avatar for Will Green
    Will Green November 18th, 2009

    Calling back into the controller from the view just doesn't feel quite right to me. Wouldn't it be better to instead create a View Model that encapsulates all the specific, for lack of a better term, "sections" of the view to be the rendered? The main view would then call the partials, passing in specific parts of the View Model that each partial needs.
    How you assemble that view model is of course up to you (non-action methods in the controller, perhaps?), so you'd still get the re-use. You should still be able to cache the output of the partials, too.
    Or am I totally missing the point?

  5. Avatar for ParseInt
    ParseInt November 18th, 2009

    @Will Green, I totally agree with you, in all our projects we're using a base ViewModel that all ViewModels inherits from, and if there's something we need (eg a menu) to be displayed on all pages we just create an actionfilter that fills that menu in the baseview. You get the same power as the Html.Action and you get the separation you're used too. And you dont get the performance hit you get with Html.RenderAction (which was pretty significant the last time i checked in MVC Futures using JetBrains DotTrace).
    @Phil: Is the performance problem fixed in this version?
    My two cents..

  6. Avatar for Scriov
    Scriov November 18th, 2009

    Something like this is just what we've been looking for, but having seen the implementation I'm not sure...
    We've been looking for a way to display multiple sets of data on one page. Assume the page is a Products list, but in the UI somewhere there is also a Private Messages toolbar.
    Currently, the only way to do this (to my knowledge) is for the single action to populate the ViewData for Products & Private Messages which is no good.
    We were hoping RenderAction would solve the issue:
    Summary(); // Lets say this is the one that we'd want to use,
    // it sets it's own View Data so that
    // Products/Index doesn't have to
    Then, within a view somewhere one could have:
    Html.RenderAction("Messages", "Summary");
    But it doesn't sound like we'd be able to set a controller name?
    Others above have suggested using a ViewModel and Action Filter to set data in said model. This (to me) doesn't sound right either. It should be actions that set data, not passive, out-of-the-way
    places like Action Filters (not to mention in a modular application one couldn't easier have a base ViewModel anyway; each component could, in theory, plug into a different MVC Shell app and this shell have may not have Private Messages so it wouldn't make sense to have a view model that represents that. Same goes for inherited controllers that have the MessageSummary action built in; it's not valid in every use of the module.)
    Again, I'm looking to focus on Actions having a single responsibility which is to populate their data, not data for all of the other components on the screen (it is the Products action afterall, not ProductsAndMessages).
    Does this make sense? Does it sound too crazy? Is there already an easy solution to this in MVC?

  7. Avatar for Lee Smith
    Lee Smith November 18th, 2009

    There's something not right about views calling controllers.
    Use Partial Requests!

  8. Avatar for Mohamed Meligy
    Mohamed Meligy November 18th, 2009

    This is great, Haack :)
    How about expression-based overloads of this?
    Would love to be able to write something like:
    <%= Html.RenderAction(
    (MyController c) =>
    c.Menu( new MenuOptions(){Width=400, Height=500} )
    ) %>
    Is that expected to see sometime soon?

  9. Avatar for Dmitriy Nagirnyak
    Dmitriy Nagirnyak November 18th, 2009

    I think IsChildAction is not such a good property.
    It does not represent nested child-actions.
    Better one would probably be "ParentContext" or similar, so we can track the nested calls easily this way.

  10. Avatar for asper
    asper November 18th, 2009

    why do we have 2 ways on doing same thing? we don't have Html.Partial('control') where it returns a string of the control.

  11. Avatar for Qun
    Qun November 18th, 2009

    Ive two controllers from different area.
    I cannot use renderaction method.
    did I missed something, or this is a bug?

  12. Avatar for Haacked
    Haacked November 18th, 2009

    @Steve, you can do this already.
    <%= Html.Action("Menu", new {width=400, height=500"}) %>

  13. Avatar for Haacked
    Haacked November 18th, 2009

    @Scriov I'm not sure I understand. You can set the controller name. I didn't show every overload in my blog post.

  14. Avatar for Haacked
    Haacked November 18th, 2009

    @asper, we do have Html.Partial now. Use Render***(...) if you're rendering a large subview. It's more efficient.
    Use Html.Action or Html.Partial if it's important to you to have a string returned (for unit test purpose or if your view engine doesn't support the Render*** methods.

  15. Avatar for Haacked
    Haacked November 18th, 2009

    @Qun you need to specify the area parameter just like you would if you were using Html.ActionLink.
    <%= Html.Action("Menu", new {area="MyArea"}) %>

  16. Avatar for asper
    asper November 18th, 2009

    html.Partial now? cool! 2.0 is gonna be great

  17. Avatar for Shiju Varghese
    Shiju Varghese November 18th, 2009

    Phil, This is really COOL.

  18. Avatar for Steve
    Steve November 18th, 2009

    Not sure you understood my point; I realize you can wrap it in an anonymous class rather than putting it in an explicitly declared one, which is a good start. But is there a way to hook in to the request parsing you've built for actions, when delegating to another action? There are all sorts of reasons that's useful - mainly, being able to pass through URL values without having to understand them. Otherwise you're stuck with:
    <%= Html.Action("Menu", new { width = int32.Parse(Request.Param["width"]), etc...

  19. Avatar for Ali
    Ali November 18th, 2009

    glad to hear added to the core product.
    happy MVCing !

  20. Avatar for Gina
    Gina November 18th, 2009

    I really enjoy ASP.NET MVC, and I've been using Html.RenderAction since it's first arrival in the futures assembly, but after testing it's still a big performance hit, is this something that will be fixed in the final version?

  21. Avatar for Haacked
    Haacked November 18th, 2009

    @Gina we will investigate the performance hit and try to mitigate it as much as possible. Please consider what you're asking RenderAction to do.
    Basically it's very similar to making another request since we need to run through routing to make sure we have the appropriate route data and context to call the action method. So each call to RenderAction is going to add up.

  22. Avatar for born2code
    born2code November 19th, 2009

    so i have been doing this for a while now by simply using jquery to call my PartialResult controller method and setting the html with the PartialView that comes back.
    does the exact same thing with the added benefit of async loading the partial view, without having to rely on a separate RenderAction method.

  23. Avatar for J&#248;rn Schou-Rode
    J&#248;rn Schou-Rode December 13th, 2009

    I am currently using the RenderAction helper method from the futures assembly, and one problem I have with it, is that it always creates a new instance of the controller class, even when rendering child actions from the controller already in action. If the controller has an expensive initialization (constructor or Initialize method), using RenderAction causes an unnecessary overhead.
    Is the behavior the same in ASP.NET MVC 2? Couldn't RenderAction just invoke the child action on the already instantiated controller, in the case where the type of the parent and child controller is the same?

  24. Avatar for Robert Koritnik
    Robert Koritnik December 28th, 2009

    ChildActionOnlyAttribute to let through Ajax requests.
    As I've skimmed this attribute's code it seems that it only passes through requests when a certain action is called using Html.Action/RenderAction. This is probably not exactly how it should work. It should also pass through all Ajax requests because we could make an Ajax request to return a partial view.
    Forms in partial views
    Let's say I have a controller that returns a partial view with a comments form. I call this controller action within NewsPost.aspx view which also has a general partial view "Quick Search" displayed on the same page with a separate form element. If I write


    in both partial views (rendered with RenderAction()), where will those two views post back? To the URL of the main view maybe?
    So if I set a certain controller and action in my BeginForm() will still present me with other problems, since I won't know what to return from my controller action... I don't know which view vas displayed on the client to return the same one, and returning a partial view won't work either, since it was a full page post...
    How do I do this kind of scenarios?

  25. Avatar for haacked
    haacked December 29th, 2009

    Don't use that attribute. It's not required. It is meant to block direct web requests. Ajax is a direct web request.

  26. Avatar for haacked
    haacked December 30th, 2009

    Regarding forms in partial views, I generally don't put the form in the partial view. I'll do something like this:
    <% using(Html.BeginForm()) { %>
    <% Html.RenderPartial("Comments"); %>
    <% } %>
    Otherwise, you'll have to add something extra to the form to tell the controller what it should do.

  27. Avatar for Robert Koritnik
    Robert Koritnik December 30th, 2009

    Well, using forms in partial views and displaying them using RenderPartial() is a minor issue, because there's still only one controller action being executed.
    Things tend to get more messy when you display partial views using RenderAction(). When you'd use Html.BeginForm() it wouldn't add action attribute to it, so all would post back to your main view. But even if you had provided some other controller and action, it wouldn't work, because your action can (and in some cases it has to) return a PartialView. This action would be executed as a result of an HTTP request and not as a result to RenderPartial() call.
    Now think of returning something back? What? A view! But how would you know which one if your action is being called within various different pages?
    I think that avoiding FORM element usage in partial views isn't a solution here. Let me explain why by a practical example:
    Your site has two major "controls" (actions that are called by RenderAction() and return PartialView), that are part of every view: Logon with two inputs and a button and a Quick search with a text box and a button.
    1. you can't have both controls in the same form, because there might be another form as the main page content (let's say someone is adding a comment to a post that's being displayed in the view)
    2. Having them all contained within the same form means submitting a comment would result in sending comment, login and search values as well. What if I had entered something in the search box and then entered comment fields and submitted them? What should I do then? Display search results or add a comment?
    3. Having them in separate form elements solves the problem. Clicking on Search button takes me to search results. This one is easy, because search results probably are going to be displayed in a completely separate view.
    4. But what happens when a user logs in? You have your blog post page with comment form. It displays a particular post related by route values. Then your user decides to log in. They enter their credentials and click "Login" submit button. Form action would be set to go to ../Account/Login. Ok. So the call processes form values and authenticates user. But what's next? This action should return a partial view with user information that would be displayed in place of a login form. But it can't because there was a full page postback. It has to display the same page that was displayed previously.
    I hope that by this very common everyday example I've explained the problem of RenderAction() helper. It's the right tool for the job, but it doesn't quite provide the necessary functionality.
    I have an idea how this should work, but I haven't tested it thoroughly yet...
    The thing is that all form should post back to the main view's URL. Every form element should also have a hidden input with data about the actual controller+action[+additional route values] of the form. When the page is being processed, only the control (rendered by RenderAction()) that's related to this controller+action provided in the hidden field should process as a POST request. All others should only be renedered as GET.
    1. Main view will get displayed as a GET call to some action.
    2. Some form that is posting data will be processed with POST.
    3. Other forms will be processes as GET.
    This would be possible, because RenderAction() does initiate a new MvcHandler with generated http context (including request).
    1. Messing around with hidden fields reminds me a bit of web forms...
    2. All forms (as FORM elements) should be part of partial views displayed in the main view by RenderAction().
    I guess everything else should work as expected.

  28. Avatar for haacked
    haacked December 30th, 2009

    I'd argue your login form should post to a login action which redirects back to the original form, if your login is a normal form post. If it's an Ajax login, just return a login status view. In that case it doesn't matter where it's called from.
    I think you may be over thinking this.

  29. Avatar for Robert Koritnik
    Robert Koritnik December 30th, 2009

    Maybe so... But the thing is that this application should also work script free. So Ajax calls may not be allowed.
    My example was taken from the real world, but may not have been the perfect one. The case of a login control at the top of the page would usually work Ajax style. You're right.
    Anyway. While I was thinking about this hidden input and relating to web forms it made me think a bit. MVC 1 is already using hidden fields when you display checkboxes, so hidden fields may not be the wrong way of doing this.
    I still think that MvcHandler + Html.BeginForm would change things significantly if they worked as I suggested. Something I should play with I guess. And I don't think this would overcomplicate the framework too much.
    BTW: How did other MVC frameworks solve this?

  30. Avatar for haacked
    haacked December 30th, 2009

    If JavaScript is turned off, then the form is fully posted to the login action and redirected back to the URL you were on. I believe this is how other MVC frameworks do it because they don't have the equivalent of RenderAction AFAIK.

  31. Avatar for Roger Rogers
    Roger Rogers January 7th, 2010

    > I'd argue your login form should post to a login action which redirects back to the original form
    I try to use return Redirect("..."); in the RenderAction, but I get the error "Child actions are not allowed to perform redirect actions."
    How can I make my RenderAction action return a redirect so that I can use the PRG pattern?
    (MVC newbie, so forgive me if the answer is obvious)

  32. Avatar for Roger Rogers
    Roger Rogers January 7th, 2010

    Nevermind, this works as expected, e.g.:
    return RedirectToAction("Details", "Steps");
    Not sure what I was doing wrong, but the error is gone.

  33. Avatar for bill xie
    bill xie January 22nd, 2010

    Sometimes this would be useful like Server.Execute in WebForms. But from the standpoint of architecture this sounds not a good approach since action like Menu is only a portion of View and should stay with View only. Unfortunately it produces an opportunity to allow developers to put View into Controller and thus may be a nightmare for change and maintenence.
    On the other hand, a Web Form can encompass lots of postback triggers which corresponds to action in the MVC framework. Looking at View, so many actions in a Web Form share the same view. I am afraid this is difficult in the MVC framework. User control can mitigate this job. However, it is still a question how to write less Views or have actions share the same view.

  34. Avatar for Joe Future
    Joe Future January 28th, 2010

    In my app, I have extensions that know how to render their own configuration forms. I've been using RenderAction to call the "configure" action on each extension's controller, which renders the configuration form view. I'd like to have the extensions' controllers handle the form submit as well and then redirect back to the "manage all extensions" admin page. I was able to do this in MVC v1, but because of the same issue Roger Rogers mentioned above, the child controllers can't redirect now. What should I return from the extension controller's action that handles the form submit?

  35. Avatar for Ta Duy Duc
    Ta Duy Duc February 3rd, 2010

    Hi haacked. today i have a chance to test Html.Action on my controller, the concept is great for rendering static content, like menu, or cached content that you can cached, but like the before html.RenderAction, it's having the same problem issue on running too sync.
    I tried to run a Html.action on my page with a query in the action that im trying to call. The page have setup 5 Html.action call. My result in my profiler is:
    Async 1 - From main Controller - 3.1s
    Async 2 - From main Controller - 2.2s
    Async 3 - From main Controller - 2.4s
    The total operate cost here is only ~3s since it's async
    Sync 1 - Html.Action - 2s
    Sync 2 - Html.Action - 2s
    Sync 3 - Html.Action - 2s
    Sync 4 - Html.Action - 2s
    Sync 5 - Html.Action - 2s
    -> in here is another 10s to run
    This issue is always the issue of calling Action in Controller. I guess unless you can render the whole view and then detect Html.action, run them async, then render the final output. I believe there is almost no way to make this sufficient.

  36. Avatar for Tim
    Tim April 21st, 2010

    Hi All,
    I was just wondering if I can wrap the RenderAction method within an extension method, so I can do a bit more processing in the htmlhelper before calling the RenderAction.
    System.Web.Mvc.Html.ChildActionExtensions.RenderAction(helper, "account", "login");

    called in my own htmlhelper still calls the method using the control and action of the current request...
    Any ideas why?

  37. Avatar for Igor
    Igor December 16th, 2010

    what if i want to display a sub menu? the scenario is like this: in an site master, i have a div where i render all the menu items (on top of the site) and a submenu, (somewhere on the left). i guess they have to be in a site master, as this is the only way to make the menus visible throughout the whole page.
    when i call render action method, i have a problem of filtering the submenu items depending on the menu item selected currently, as every source of routevalue collection returns me values of the action executed currently, not the one that initiates that action.

  38. Avatar for hhgregg
    hhgregg February 3rd, 2011 me understand the differences between Html.RenderAction and Html.Action. Is it that Html.RenderAction will render the result directly to the Response (which is more efficient if returning a large amount of HTML). Whereas Html.Action returns a string with the result. Is this correct?

  39. Avatar for haacked
    haacked February 4th, 2011

    @hhgregg That's correct.

  40. Avatar for Mike Vanderkley
    Mike Vanderkley August 9th, 2011

    Hi Phil, I have a route class which returns a RouteValueDictionary. This var includes area/controller/action. So for methods like Html.ActionLink and Html.BeginForm; I have made extension so action defaults to null. So I endup with en extention where I can do @Html.ActionLink("Edit", NewsRoutes.Edit(news)).
    However, I cannot make a similar extention for RenderAction as the action param is required. This example does not work.
    public static void RenderAction(this HtmlHelper helper, RouteValueDictionary routeValues) { helper.RenderAction(null, routeValues); }
    This appears inconsitent with ActionLink and BeginForm. (Mvc3 btw).

  41. Avatar for Ben
    Ben March 19th, 2012

    Hi Phil
    why there is no Html.Route(routeName: "MyRouteName", new { /*data*/ }

  42. Avatar for Mark
    Mark May 1st, 2012

    Hi Phil,
    Can you share the overload to use a different controller please?
    I have been looking into this for hours. Looks like you have to pass in the values from the parent view at load and use the viewbag, but that doesnt seam very dynamic. I would be happy to just fire the partial view and pass a parameter to load the child records. Seams to me that partial views would almost always have a different controller and would often have related child records.
    Thanks, have been reading lots of your posts. Very helpful.

  43. Avatar for haacked
    haacked May 7th, 2012

    @Mark not sure I understand your question.

  44. Avatar for Richard Weeks
    Richard Weeks July 18th, 2012

    Professional ASP.NET MVC 3 (Wrox, 2011) pp115-117 - The code and text is identical to this post. Sanctioned?

  45. Avatar for haacked
    haacked July 18th, 2012

    @Richard Well I wrote that chapter of Wrox based on what I wrote in this blog post. It's not exactly the same content, though it's very similar because I wrote both. :)

  46. Avatar for shivkumar
    shivkumar September 12th, 2012

    I have use @Html.Action, so how should i load javascript while rendering action each time means while loading action ?

  47. Avatar for safipeti
    safipeti November 14th, 2012

    Hey, Nice post, that's exactly I was looking for!
    Just one thing, in Razor, if you attempt to use like this:
    @Html.RenderAction("SideCategories", "Category")
    it throws an exception, stating that you have used inproper overload, however, (actionName, controllerName) overload is allowed.
    But, if you compose like this:
    @{Html.RenderAction("SideCategories", "Category");}
    It works as expected!
    Thanks again!

  48. Avatar for Ahmed Mahmoud
    Ahmed Mahmoud March 4th, 2013

    thanks alot :)

  49. Avatar for Sushil Kumar
    Sushil Kumar October 22nd, 2013

    Great Article...solved my issue...Thanks!

  50. Avatar for Daniel
    Daniel January 15th, 2014

    Excelent! IsChildAction is very handy when you need to address partialview specific logic in onActionExecuting method.

  51. Avatar for Zeeshan
    Zeeshan February 16th, 2014

    I am having problem with rendering with the above specified way actually I have just passed the html string to partialview method as object but its not rendering when calling with renderaction can anyone help me out in this?

  52. Avatar for Dang Truong Hai
    Dang Truong Hai October 22nd, 2014

    Good article

  53. Avatar for Carlo Ostia
    Carlo Ostia October 20th, 2015

    RenderAction Render also the tag body. Can I avoid this? I want to render only the html of the control called with RenderControl

  54. Avatar for Naresh Dhami
    Naresh Dhami November 3rd, 2015

    A nice feature worth to take a look!.

  55. Avatar for September 9th, 2017

    The article is about RenderAction. But why no examples? In the example only "Action" is used. But all the talking is about RenderAction ... am I missing something?

  56. Avatar for haacked
    haacked September 9th, 2017

    The article is about both RenderAction and Action. They're effectively the same method. The difference is RenderAction returns void and writes directly to the response. Whereas Action returns an HtmlString with the output. That makes Action easier to use than RenderAction. The syntax is much cleaner, hence I used that for my examples.