posted on Thursday, January 17, 2008 11:14 AM by scotts

asp.net mvc RenderUserControl controlData

I've had a little trouble getting data from a asp.net mvc ViewPage to a ViewUserControl. The html extensions toolkit provides a RenderUserControl method that has an overload that allows for "controlData" to be explicitly sent from the ViewPage to the UserControl. I much prefere the approach of explicitly sending the required data to a user control instead of assuming that it will implicitly grab it from somewhere. I've found a few things that make this process work better for me. First, I send the data to the ViewUserControl as an anonymous type, and secondly all of my view user controls inherit from a base AppViewUserControl that I create for the application. In this base class I override a few ViewData methods to get over what looks like a bug with the current implementation of the the HTMLExtensionUtility. I was running into a problem where the "ViewData" property on the ViewUserControl should be of type object, and instead it is of type System.Web.Mvc.ViewData, and so can't be treated as an anonymous type.

So, in my base ViewUserControl class I add the following:

Partial Public Class AppViewUserControl
    Inherits System.Web.Mvc.ViewUserControl

    Private _ViewData As Object
    Protected Overrides Sub SetViewData(ByVal viewData As Object)
        MyBase.SetViewData(viewData)
        _ViewData = viewData
    End Sub

    Public Overloads ReadOnly Property ViewData() As Object
        Get
            Return _ViewData
        End Get
    End Property

End Class

There is probably a better way to do this, and this may have side effects that I haven't hit yet. But it seems to do the trick for me. Basically, all I'm doing is duplicating the storing and retrieving of the passed view data from the page to the control, so that the control's view will see the data as type object.

Once this is done, then from a mvc ViewPage, we can explicitly pass the required UserControl data as an anonymous type like this:
<%=Html.RenderUserControl("~/Views/Shared/Status.ascx",  New With {.Status = Status, .Message = Message})%>

Obviously, Status and Message are just examples in this snippet of code of data that is local to the ViewPage, and you would use your own data and properties probably from the page's local ViewData.

With this in place, then I'm able to do something like this in my ViewUserControl to use this data:
<div id="system_status"><%=ViewData.Message%></div><%=ViewData.Status%></div>

I personally like the idea of explicitly passing required data from the ViewPage to the ViewControl, similiar to how rails allows a render :partial, with a :locals symbol to tag the hash of local data for the partial.

Comments