I’ve
Since Preview Release 5 of the ASP.NET MVC Framework, the handling of User Controls have changed a bit. The helper method RenderUserControl
have been replace by RenderPartial
. A little annoying thing when a User Control is imported into a View is a tiny difference in how it’s coded that is easily overlooked. So if you get this cryptic error:
CS1502: The best overloaded method match for ‘System.IO.TextWriter.Write(char)’ has some invalid arguments
It’s because you’ve been inserting the User Control with <%= RenderPartial("ViewName") %>
, instead of <% RenderPartial("ViewName"); %>
. (Note the equal sign before the method call and the semicolon after).
Passing a Data Object from the Controller to the View
Suppose you have a class called Car
with the properties Make
and Color
, that you want to render using a User Control.
In order to pass data to the User Control, you first have to pass it from the Controller to the View. This is done by either sending the Data Object in the Return
statement in a ActionResult
method like this:
public ActionResult List()
{
List<Car> cars = cars.GetCars();
return View(cars);
}
Or assign it explicitly to the ViewData
object like this:
public ActionResult List()
{
List<Car> cars = cars.GetCars();
ViewData["Cars"] = cars;
return View();
}
I often find it more convenient to do it the first way, but when you have several data objects that you want to pass, you’ll have to use the second way too.
Passing DataObject to the User Control
Like I mentioned earlier in this article, the MVC Framework has a useful helper method for inserting User Control into Views. It’s called RenderPartial
. Before the Preview Release 5 it was called RenderUserControl
and was used a little different. So don’t confuse the two.
It’s used like this:
<% Html.RenderPartial("~/Views/Cars/List.ascx"); %>
To pass a list containing several instances of Car
from the View to the User Control is easy. You just add it as the second parameter in the RenderPartial
call like this:
<% Html.RenderPartial("~/Views/Cars/List.ascx", ViewDataModel); %>
or if you explicity assigned it to the ViewData object:
<% Html.RenderPartial("~/Views/Cars/List.ascx", ViewData["Cars"]); %>
Displaying the data in the User Control
In the User Control you have to first add a reference to the class Car
in the CodeBehind. And since you want a list of it you have to use List<>
around it:
public partial class List : System.Web.Mvc.ViewUserControl<List<Car>>
{
}
In the .ascx
you then access the data by referencing to the ViewData.Model
, just like you would in a View. So rendering a simple list of cars would look something like this:
<ul>
<% foreach(Car car in ViewData.Model) { %>
<li><%= car.Make %>, <%= car.Color %></li>
<% } %>
</ul>
What’s up with the name?
I find it a little confusing that the Helper method is called RenderPartial
when it’s actually a User Control that you render. Wouldn’t it be more logical to call the User Control, Partial View or something instead? Or have I missed something?
To read more about the ASP.NET MVC Framework and how to pass data objects, check out Scott Guthries excellent blog post, ASP.NET MVC Framework (Part 3): Passing ViewData from Controllers to Views. It’s on an older release but most of it still applies.
Happy coding!
November 13, 2008 at 11:44 am
you are great, i lost 3 hours to find how these damned controls works…
thank you very much!!
January 6, 2009 at 1:27 pm
Thanks a lot for this article!! You made my day 😉
January 16, 2009 at 8:09 pm
HI. I believe it is called RenderPartial because the rendered html fragment is just a part (or partial) of the calling page? And it is not used just for rendering UserControls — you can render views as well, if it made more sense to so versus a ViewUserControl.
Interestingly enough, in previous previews of MVC, it was called RenderUserControl.
January 17, 2009 at 12:39 pm
Ryan: Ah, that make sense. I never thought of that you could render other stuff than ViewUserControls with it. Thanks!