views:

853

answers:

2

Hello,

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

+2  A: 
  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.

zihotki
If you use protection, the likelihood of passing VD is greatly decreased
Rex M
What do you mean under "protection" and why is it decreased? Controls can use value bindings so they will be able to load values from ViewDataDictionary or from model.
zihotki
@Rexm lol! @zihotki enjoy the breeze.
Chris Ballance
+2  A: 

I am tracking with zihotki on this one. With #2 I will add a caveat, however. In the default implementation, which uses neutered ASPX and ASCX as views, creating MVC controls (use the template to ensure your dog is neutered) is the best option.

Now for the caveat. ASPX and ASCX do not have to be the views. If you look at Phil Haack's blog, you will see some other view engines mentioned, like the Spark View Engine (http://tinyurl.com/5jok4f). In fact, Phil has set up a sample of using alternative view engines in this entry: http://tinyurl.com/5sz5mt.

I am not suggesting that you move to other view engines, only that there is an option, if you find one that better fits your problem domain. Sometimes it is better to stick with the out of the box implementation. In this case, keep things simple with ASCX controls.

By the way, if you are seriously getting into MVC as your UI story, you should look at the codeplex projects for MVC (http://tinyurl.com/dbpn8c). The most important here is probably MVC.Contrib, but there are a few other gems in the list.

Gregory A Beamer