C# – Passing ViewData to ViewPage in ASP.NET MVC

asp.net-mvccnet

I'm trying to build a custom control in ASP.NET MVC. The thing that I want to avoid is mixing the view (html) and the code (C#) in these controls.

After hours of googling and struggling with this problem I've finally thought of creating helper methods that use the ASP view Engine thought the ViewPage class.

I'm able to create an instance of the class and even load an ascx template using LoadControl and LoadTemplate methods but the problem is that when I pass a ViewData object to an instance of ViewPage class I cannot see the ViewData in the ViewPage and I'm getting this error:

The ViewUserControl '~/Components/Controls/EditableLabel/Views/EditableLabel.ascx' cannot find an IViewDataContainer. The ViewUserControl must be inside a ViewPage, ViewMasterPage, or another ViewUserControl.

Generally the final effect that I want to achieve is loading controls with some parameters, these parameters should be readable in the template (ascx).

example:

<% Html.EditableLabel(Writer, "memberName", "Name", "Antonio", "/identity/updateProperty", "memberName"); %>
  1. Is there a way to pass the ViewData to the ViewPage instance that I create?
  2. Is there a smarter way to create custom controls/widgets in ASP.NET MVC?

Thanks in advance

Best Answer

  1. You can pass VD to the VP from controller via "return View(...)" or via "ViewData[name] = value".
  2. It's better to use ascx controls which are inherited from ViewUserControl in order to create a custom control. In this way you easily can pass data to it:

    <% Html.RenderPartial("FooControl", new FooViewData(){ Name="aa",  Type="awesome", Id = 2}); %>
    <% Html.RenderPartial("FooControl", new FooViewData(){ Name="aa", Type="awesome", Id = 2}, ViewData); %>
    

And all necessary parameters you can define in your FooViewData class.

If you really want to write an extension to the HtmlHelper which will load some ascx controls you should look at a Repeater class in MvcFutures (sources of MVC are here). But I'm sure that in a common case you'll not need this.