When to use Html.RenderPartial and Html.RenderAction in ASP.NET MVC Razor Views

In this blog post I want to show examples when to use Html.RenderPartial and Html.RenderAction when creating web sites in ASP.NET MVC using the Razor view engine.

Some background information on Html.RenderAction and Html.RenderPartial

Html.RenderAction is a somewhat contentious feature because it invokes a controller action.

This means each time it’s called a new request (which has to go through the ASP.NET MVC pipeline) is made.

As shown below ASP.NET MVC requests are routed to a controller. It’s the controller that decides what view to call and what data (model) to pass to it.

Architecture for Html.RenderActionA view has one responsibility and that’s to render HTML. It’s supposed to be simple, it doesn’t know (or care) where the data in the model comes from.

The thing MVC traditionalists frown upon is the fact that Html.RenderAction can execute child actions in ASP.NET MVC views.

However given that Html.RenderAction just like an AJAX request is a form of sub request, the case against seems somewhat outdated and doesn’t take into the account using Html.RenderAction will allow you to separate concerns of models and controllers as we will see later in this post.

For Html.RenderPartial the content of the partial view is added to content of the host view, either directly to the response output (or by using a StringWriter if you use or Html.Partial).

Examples of when to use Html.RenderPartial and Html.RenderAction

The mockup below shows a blog post with comments and a list of categories in a side bar.

ASP.NET MVC mockup

When to use Html.RenderPartial (or Html.Partial)

For the page we’re designing I would create a view to show the blog post and call Html.RenderPartial to output the comments

@model WhenToUseRenderActionAndRenderPartial.Models.ShowPostViewModel
@{
    ViewBag.Title = Model.Post.Title;
}

<section>
    <article>
        <header>
            <h1>@Model.Post.Title</h1>        
        Posted on | <time datetime="@Model.Post.DatePublished.ToString("s")">
           @Model.Post.DatePublished.ToLongDateString() 
        </time> | @Model.Comments.Count() Comments
        </header>
        @Html.Raw(Model.Post.Content)
    </article>  
</section>
@{Html.RenderPartial("_Comments", Model.Comments);}

The partial view for comments would look like this

@model IEnumerable<WhenToUseRenderActionAndRenderPartial.Models.Comment>
<section>
    <header>
        <h3>
            Comments</h3>
    </header>
    @foreach (var comment in Model)
    {
        <article>
            <header>
                @comment.Author on 
                <time datetime="@comment.DateCreated.ToString("s") ">
                    @comment.DateCreated.ToLongDateString()
                </time>
            </header>
            <img alt="@comment.Author" src=@comment.ImageUrl />
            <p>
                @comment.Content
            </p>
        </article>
    }
</section>

This means the ShowPost action in the Blog controller

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using WhenToUseRenderActionAndRenderPartial.Models;

namespace WhenToUseRenderActionAndRenderPartial.Controllers
{
    public class BlogController : Controller
    {        
        public ActionResult ShowPost()
        {
            ShowPostViewModel viewModel = new ShowPostViewModel();
            viewModel.Post = new Post
                            {
                                Title = "Blog Title",
                                Content = "<p>Lorem ipsum dolor sit amet</p>",
                                DatePublished = new DateTime(2010, 10, 5)
                            };            
            viewModel.Comments = new List<Comment>()
                                             {
                                                 new Comment()
                                                     {
                                                         Author = "Andrew",
                                                         Content = "I think",
                                                         DateCreated = new DateTime(2010, 10, 5)
                                                     },
                                                new Comment()
                                                     {
                                                         Author = "Bill",
                                                         Content = "I reckon",
                                                         DateCreated = new DateTime(2010, 10, 5)
                                                     },
                                                new Comment()
                                                     {
                                                         Author = "Chris",
                                                         Content = "My opinion",
                                                         DateCreated = new DateTime(2010, 10, 6)
                                                     }
                                             };
            return View(viewModel);
        }
    }
}

needs to pass a model with properties for the blog post and its comments to the view.

public class Post
{
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime DatePublished { get; set; }
}

public class Comment
{
    public string Content { get; set; }
    public string Author { get; set; }        
    public string ImageUrl { get; set; }
    public DateTime DateCreated { get; set; }
}

public class ShowPostViewModel
{
    public Post Post { get; set; }
    public IEnumerable<Comment> Comments { get; set; }
}

When to use Html.RenderAction (or Html.Action)

So while we could add a property for categories to the ShowPostViewModel used for the ShowPost page and use Html.RenderPartial to display them, we have to add a category property to every model in our solution where categories are shown.

public class ShowPostViewModel
{
    public Post Post { get; set; }
    public IEnumerable<Comment> Comments { get; set; }
    public IEnumerable<Category> Categories { get; set; }
}

public class AnotherViewModel
{
    public string StringToOutput { get; set; }
    public IEnumerable<Category> Categories { get; set; }
}

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And using a base class with a categories property and have ViewModel classes inherit from it would just be bloating models with unrelated data and concerns.

public class ViewModelBase
{        
    public IEnumerable<Category> Categories { get; set; }        
}

public class ShowPostViewModel : ViewModelBase
{
    public Post Post { get; set; }
    public IEnumerable<Comment> Comments { get; set; }
}

So if you want to display the same information on multiple pages and the data doesn’t necessarily depend on or isn’t related to the rest of the page, something like a widget to display categories then I would use Html.RenderAction.

As shown in the markup below Html.RenderAction is called from the layout page for the blog post.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
</head>
<body>
    @RenderBody()
    @{Html.RenderAction("Show", "Category");}
</body>
</html>

Jag Reehal’s Final Thought on ‘When to use Html.RenderPartial and Html.RenderAction in ASP.NET MVC Razor Views’

In cases where a model for the page is already populated with all the information required I would use Html.RenderPartial.

If the same information is shown on multiple pages it’s likely that the data needs to be in its own model so I would use Html.RenderAction. As shown in this post I would say layout pages are going to the most common place Html.RenderAction will be used.

Comments

  • nick4eva

    Great post. It was very helpful for me.

  • Cesar

    I want to be the first one to thank you for such a good article. 10!

  • http://www.lessonist.com niaher

    Good post. Thanks.

  • Joseph

    And the Action “Show” from the CategoryController returns what? a view?
    That’s the thing I dont understand…
    Thanks

  • http://www.arrangeactassert.com Jag Reehal

    Hi Joesph,

    RenderAction returns a view which is rendered directly into the Response.

    See Phil Haack’s post about ‘Html.RenderAction and Html.Action’ for more information.

    Cheers,

    Jag

  • nenadg

    great example, this helps me a lot, thanks

  • Jet

    Very clear article. Nicely presented. Thankyou for your effort here.

  • Forest

    Awesome post.  Clear, concise, and pragmatic. 

  • Kevin Grieger

    Very good, I totally agree with this methodology. I have been reading like crazy to find an alternative to passing in all those widget models, and this really is the best way.
    Thanks!
    ~kevin G.

  • tan

    great article

  • Alextito52

    Muy Bueno

  • Fraas

    that’s it’s very very helpful article , I loved it so much

    thanks

  • Dan

    This really solves my problem with passing drop down list data with every view, i was doing the same thing by putting the list of data in every view model class. 

  • http://www.facebook.com/people/Jon-Swoveland/773837989 Jon Swoveland

    Thank you!!! I’m just starting out with MVC this was the first article I’ve found that clearly discusses the subject or RenderPartial vs RenderAction – it’s like a fog has lifted!
    Cheers

  • Leon

    Thanks for your article. It is over a year old, but I hope you are still responding to comments on it.

     I am new to MVC and I am using version 3. In your example, in the layout page line that contains Html.RenderAction(‘Show”, “Category”) , where is the “Show” action located?  I am trying to implement a menu of dropdowns that will render via the layout regardless of the View in the “content” area (RenderBody()).  I have tried the default Index action in a specific MenuController as well as actions in the HomeController. Below is the Index action in the MenuController:

                Menu Example   
                @{Html.RenderAction(“Index”, “MenuController”);}   
                @RenderBody()   
                This is the footer   

    But, no matter what controlller or action I use I am getting:

    {“Execution of the child request failed. Please examine the InnerException for more information.”}

    I am not getting enough information in other posts related to this error because no one in the posts is trying t do this that way I am.   What am I doing wrong?

  • Anonymous

    Hi Leon,

    Your code looks OK and I’ve called RenderAction from a layout page with out problems.

    Without looking at more of your code it’s difficult what the problem could be.

    Have you tried breaking the problem down? E.g. starting with the view for the menu controller returning something simple like some text and without a layout page.

    If that works then start adding back in components to find what breaks it.

    Cheers,

    Jag

  • Wiebe Tijsma

    Hi, thanks for the article… Maybe a bit late, but what’s good to mention here is that one of the nice side effects of going through the entire ASP.NET MVC stack with RenderAction is that action filters like OutputCache are also working, giving you an easy way to cache parts of your page…

  • Dipanki99

    This post is helps me a lot.Thanks …:)

  • Andre

    Excellent

  • http://www.facebook.com/storefront.doors Storefront Doors

    I tip my hat to you for the way you articulated this example. It is not necessary to be so technical when it comes to explain software, and you’ve just proved that.

  • Naresh Kumar

    God bless you for giving a wonderful example, please can you show me an example of Repository Pattern in mvc 3

  • Vijay Rakshithmuralidhar

    Good Post! Thanks for sharing!