R – ASP.NET MVC – How to achieve reusable user controls and maintain DRY

asp.netasp.net-mvcdryuser-controls

First post so please be gentle 🙂

When creating user controls in ASP.NET MVC, what is the best way to structure the code so that the controllers that invoke views that use the user controls do not all have to know so much about the controls? I would like to know a good way to maintain DRY while using user controls in ASP.NET MVC.

Please note, this question only pertain to user controls that require special handling and logic on a postback. I have no problem creating nice DRY code for user controls that are either view only (using RenderPartial) or that require some pre-processing to create the appropriate ViewModel (using RenderAction).

Also, this question pertains only to achieving reusable controls within an application. I am not worried about reusability between applications at this point.

To give a specific example, let's say I would like to create a 'Quick Add' user control which contains three entry fields, First Name, Last Name and Company Name and a submit button. When the QuickAdd functionality is used, the following steps should be performed independent of what page the control is on:

  1. Validate that the fields were not empty, if they are, show an indicator.
  2. Perform a lookup to a repository to see if the Company already exists, if not; create it.
  3. Create a new contact associated to either the existing company or the newly created company
  4. Re-render the existing page. If no validation errors, the user would see the exact same page again, otherwise the same page with validation errors.

My main problem with achieving DRY has to do with all the controllers that invoke views that contain the partial view end up having to have an Action Method to process the form submission from the Quick Add. Even if I break out the logic for processing the information into a separate controller and invoke that method from each of the other controllers it seems like a burden that each and every controller that invoke views that have reusable controls have to have that knowledge.

The other option I looked at was to have the reusable control always submit to a specific action method / controller but then there is no way for that controller to know how to re-populate the model appropriately for the specific controller that invoked the view that contained the reusable control (in step 4).

I am aware that there is talk of subcontrollers in MVC 2 (from this question ASP.NET MVC – Contained User Controls) but since it is not there yet, what is the best way to structure the code to achieve maximum reusability while maintaining DRY?

Is there an alternative to having to have all the controllers that invoke views that use a reusable control (with the characteristics of the one described above), having to have an Action Method to process the information from the control?

Best Answer

At the end of your post, you ask "Is there an alternative to having to have all the controllers... having to have an Action Method to process the information from the control"

The answer for that question is to write a custom model binder. Your custom model binder can be responsible for the populating the values from the incoming form control(s) into model or properties used by all of the controllers. Normally, you want to separate the validation from the model binding, but there is no reason that you couldn't combine them as well.

I highly recommend 6 Tips for ASP.NET MVC Model Binding for a deeper discussion of the topic along with some good references.