In usability we trust

UX and all things web

User Controls in ASP.NET MVC Preview Release 5

I’ve had a little trouble finding out how to use User Controls in the ASP.NET MVC Framework and how to pass data to it. I haven’t been able to find a single article that clearly explains how to do this, so I thought I’ll do a little write up on the topic.

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!

4 Comments

  1. you are great, i lost 3 hours to find how these damned controls works…
    thank you very much!!

  2. Marc Van Potelbergh

    January 6, 2009 at 1:27 pm

    Thanks a lot for this article!! You made my day 😉

  3. 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.

  4. Ryan: Ah, that make sense. I never thought of that you could render other stuff than ViewUserControls with it. Thanks!

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>