WebControls In MVC... again...

I'm a big fan of MVC so far but there are certainly parts that I don't like. For example, who is responsible for logical changes to a HTML markup in a view? The Controller? The Model? Personally, I don't think either of them should which leaves the View to pick up the slack.

But the problem is that I end up with a bunch of crud in my View -- which to me looks a lot like a Classic ASP website.

It doesn't take a lot -- Just look at a fairly reasonable example...

<div class="<% if (user.IsAdmin) { 
  %>admin-icon<% 
} else if (user.IsEditor) { 
  %>editor-icon<% 
} else { 
  %>user-icon<% 
} %>" >
<!--snip...-->

I realize that you always have access to RenderPartial and you can also start using a templating engine but I still feel this is something that a WebControl could handle perfectly.

Using A WebControl For Markup

Now if your first thought was "You can't do anything to WebControls in the Render stage of the page lifecycle" then you're absolutely right. However, it is possible to gain access to earlier than that and use it with models.

This next bit of code is pretty daunting... I'd recommend you send any children out of the room and shield your eyes...

<!-- As it turns out, you can simply call it like... -->
<mvc:MyControl SomeProperty="<% #this.Model.TheProperty %>" runat="server" />

And that is about it! Really!

The second step requires that you call the DataBind function for the page... but you can't call it as part of the render (otherwise it is too late). You could use a server side script tag at the top of your page, but I recommend you just create your own ViewPage class that takes care of it for you. Below is the class that use in later examples. Again, there is an insane amount of code so be warned...

/// <summary>
/// ViewPage with Model access for WebControls
/// </summary>
public class MyControl : UserControl {

    //some point the the control lifetime call DataBind
    public override void OnLoad(object sender, EventArgs e) {
        this.DataBind();
    }

}

How About A Real Example Then?

So this sounds interesting, but how could it really be used? I've include a Visual Studio solution file with some examples that go over possible ways to use WebControls in your MVC applications.

  • Twitter Feed: Writes all of the logic and rendering of a simple Twitter feed. Uses the BoundedViewPage to attach a user name to the Property of the control. Also allows normal access (assignment from a string) so you could reuse the code anywhere.
  • Calendar: Example that uses a Calendar control and a Grid View to create a a simple page of content but uses binding to the Model to get information for all of the controls.
  • Task List: Simple task list that shows how you can use a UserControl with button click events to update the Model and then show the results on the page.
  • Crash Example: Using RenderPartial on a page that has a server form does not work correctly. However, if your WebControl doesn't use a server form (which is better anyways) then you can use all MVC features without a problem (as far as I know, that is)

Of course, I'm sure a lot of people will be against this idea but I think it is worth exploring. If you think about all of the new features that ASP.NET 4 is going to introduce (especially better control over the client side markup) then this might end up being a perfect combination!

January 31, 2010

WebControls In MVC... again...

Using Binding with Models and UserControls in ASP.NET MVC

Downloads