Hugoware

The product of a web developer with a little too much caffeine

Archive for October 26th, 2009

Render Partial — But With Arguments!

with 6 comments

One thing that I haven’t really liked about MVC was using RenderPartial instead of an actual UserControl. Its not that you can’t use them but that there is a disconnect between the control state and the render phase which makes it pretty much impossible to really work with them inline.

I say ‘pretty much’ because I’ve done a lot of work to let people use WebControls inline with MVC code.

Using the existing RenderPartial requires that you pass in the name of the UserControl that you want to render. You can also provide an object argument that is passed in as the ‘Model’ for the partial view. The UserControl can access the passed in object via the ‘Model’ property — even cast it into the correct type directly.

Personally, I use a lot of Models in my projects now. I used to suggest that you pass around objects using a wrapper for anonymous types but I’ve found that if you plan to move it from a Controller to a View or from a View to a UserControl then you ought to define a class.

Using RenderPartial Without Really Using It

So instead of calling RenderPartial directly, what about using the Model that we have in place to make the call for us. Not only that, we can even define our class to accept arguments directly. Here is an example of a simple dialog box…

using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcTest.Models {

    //simple dialog box example
    public class DialogBox {

        //rendering the dialog box
        public static void Render(ViewPage insideView, string title, string message) {
            insideView.Html.RenderPartial(
                "DialogBox",
                new DialogBox() {
                    Title = title,
                    Message = message
                });
        }

        //Properties
        public string Title { get; set; }
        public string Message { get; set; }

    }

}

Then we could simply use our code inline by calling the DialogBox.Render instead of the RenderPartial method.

<% DialogBox.Render(this, "My Title", "This is the message to display."); %>

You could also use an approach like this to make creating UserControl templates easier.

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcTest.Models {

    //simple product list example
    public class ProductListing {

        //rendering the list of controls
        public static void Render(ViewPage insideView, List<Product>, Action<Product> renderRow) {
            insideView.Html.RenderPartial(
                "ProductListing",
                new DialogBox() {
                    AllProducts = products,
                    RenderRow = renderRow
                });
        }

        //Properties
        public List<Product> AllProducts { get; set; }
        public Action<Product> RenderRow { get; set; }

    }

}

And then you could call your method inline and provide the template action.

[View.aspx]

<!-- snip -->
<% DialogBox.Render(
         this,
         products,
         (item) => { %><li><% =item.Name %></li><% }
         ); %>
<!-- snip -->

[UserControl.ascx]

<%@ Control Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<MvcTest.Models.ProductListing>" %>

<h3>Featured Products</h3>
<ul>
<% 
    foreach (Product item in this.Model.AllProducts) {
        this.Model.RenderRow(item);
    } 
%>
</ul>

The above example is probably over simplified but you probably get the idea. This may not be a big gain, but if you plan to use the same UserControl often, then this might help simplify the call.

Advertisements

Written by hugoware

October 26, 2009 at 11:38 pm