views:

508

answers:

6

In traditional ASP.NET Web Form applications, UserControls are a great way to encapsulate functionality so that it can be reused. However, UserControls don't fit well into the MVC model. They often make heavy use of ViewState and they blur the seperation of concerns that MVC promotes.

My question is, how do you best bundle a piece of functionality so it can be shared across MVC applications?

As an example, consider a from/to date-selector UserControl that:

  • allows a user to select two dates, either using a javascript overlay or by typing in day, month and year into seperate fields
  • can be configured to default to either today and tomorrow's dates or to dates of the developer's choosing
  • validates the dates that comes back from the user to ensure the from date is before the to date
  • exposes From and To properties that can be accessed by code-behind

How would I best build something like this in .NET MVC so that I can easily reuse it?

Note that to fully emulate User Control's functionality the MVC component would have to manage the submitted form data and validation - not just the presentation.

+1  A: 

Two ways that I can think of. A partial view though this doesn't really transfer well from app to app because you are moving around ascx files. Not a big pain but not my flavour.

I prefer to use WebControls. They are super easy in mvc and all you need to do is reference the library in the project and possibly in your config file and there you go.

griegs
+5  A: 

In general I would agree that user controls are nice in terms of encapsulating UI stuff, but I don't think too much has really changed in MVC. If I remember right re-using user controls across classic Asp.net projects was a pain and was never really the best way to truly create reusable components. Most UI toolkits that you bought for classic ASP.net didn't give you user controls, they gave you essentially server controls and javascript controls.

In your example, I would probably create or find a jquery (or ur framework of choice) plugin that did what you wanted on the client side. You could also build a C# wrapper around it similar to what Telerik did with some of the jquery UI controls. I do think that the word code-behind and even viewstate will disappear from your vocabulary the more you get into MVC.

If you look at what open source projects are out there for MVC you will get your answer in terms of what you should be doing.

  • The MVC Contrib app adds a lot of features by creating extension methods and helpers. Their grid control is a typical way to create a reusable component that you could use across projects

  • Telerik, created some extensions that wrap jquery controls and do asset management.

  • Finally I think if you look to the future, MVC has areas, which if I interpret it right will give you the ability to break your project apart into multiple smaller projects.
Greg Roberts
+2  A: 

Besides what is already suggested, ASP.NET MVC v2 will have generic templated input controls, see here. You can read how other people do similar techniques, for example, here:

We have exactly 1 method call for generating a form element, “Html.InputFor”. As part of that “InputFor”, it examines an input specification, that collects the PropertyInfo, any attributes, the type, any modifiers called, and selects an appropriate InputBuilder. Call InputFor(p => p.Id) and Id is a GUID? That creates a hidden input element. Call InputFor(p => p.Customer.Address) and Address is a complex type? That looks for a partial with the same name of the type

queen3
A: 

I think some of the answers have missed out on the postback functionality of controls. One way you could handle that is to pass any generic information via ViewData when rendering your partial view. That could then post back to its own control, which in turn could redirect to the UrlReferrer.

Its a little messy and use of UrlReferrer poses a security risk. But it is one way around the problem

David Archer
Yes, I think it's important to think about data coming back from the user. The wider application would ideally not be exposed to how to assemble the dates from the post data.
ctford
+2  A: 

Having considered the helpful answers from others, I will have a go at answering my own question.

It seems to me that the key difficulty with emulating UserControls in MVC is that they crosscut the concerns that MVC aims to seperate. The from/to date selector UserControl in my example incorporates elements of Model, View, Control and interation. UserControls' ability to bundle all this together is exactly the reason that they don't fit well into MVC.

That means that to create a psuedo-UserControl in MVC requires four seperate pieces:

  • A Model class - in this case an Interval class or similar
  • A PartialView that knows how to render the Model to HTML
  • A jQuery script to layer interactivity on top of the PartialView's HTML
  • A ModelBinder that can deserialise postdata into an instance of the Model class.

The ModelBinder is important because it deals with data coming back from the user. Without it, every Controller that wanted to display a to/from date selector in any of its Views would have to know how to assemble the six postdata fields - and how to cope if they were invalid or some were missing.

ctford
A: 

You can create a jQuery plugin.

TTT