I have a fairly simple data audit web application written with ASP MVC which effectively has two views of the same model for different purposes.
-
Agent view – The form filled out by the person validating information the information. Each field on the form in this view has 3 subfields:
a. Original Value – The value from the database before the call was made
b. New Value – The value provided by the person on the phone if it differs from the original.
c. Action – A general indication of what happened
-
QC View – The form filled out by someone who reviews the work performed in Agent view. Each field on the form in this view has 5 subfields:
a. Original Value – Same as above
b. Agent Value – The value provided in 1b above by the agent.
c. QC Value – The corrected “New Value” if the value specified by the agent is incorrect.
d. Agent Action – Same as above, except read only in this view
e. QC Action – The corrected “New Action” if improperly chosen by the agent.
The only differences between the two views are the subfields available. I’d like to be able to use a single view to represent both views since the overall structure of the pages is identical, and just use HTML helpers to handle the differences in subfields. What I have so far are 2 distinctly separate series of helpers (currently in the same class though could be separated):
// Agent controls
public static MvcHtmlString AuditControl(this HtmlHelper htmlHelper, string id, string fieldLabel, MvcHtmlString editControl, string cssClass)
public static MvcHtmlString AuditControl(this HtmlHelper htmlHelper, string id, string fieldLabel, string editControl, string cssClass)
public static MvcHtmlString AuditControl<COMPLEX>(this HtmlHelper htmlHelper, string id, string fieldLabel, string cssClass) where COMPLEX : AbstractComplex, new()
// QC controls
public static MvcHtmlString ReviewControl(this HtmlHelper htmlHelper, string id, string fieldLabel, MvcHtmlString editControl, string cssClass)
public static MvcHtmlString ReviewControl(this HtmlHelper htmlHelper, string id, string fieldLabel, string editControl, string cssClass)
public static MvcHtmlString ReviewControl<COMPLEX>(this HtmlHelper htmlHelper, string id, string fieldLabel, string cssClass) where COMPLEX : AbstractComplex, new()
Where the third implementations handle the more complex fields composed of multiple pieces of data (like Full name, Address, etc).
One possible solution that I’ve considered is to separate the different types of controls into different classes which implement a common interface and then pass them as type parameters to more generic HTML helpers. I think this would work but then I’d somehow need to be able to tell the view which implementation it should use to draw the view, which seems problematic because it seems to blur the line between View and Controller.
One less appealing approach that seems obvious is to pass a sort of admin flag from the controller which would be used by a generic (in logic not meaning type generic) factory helper and build the logic in it to know which series of methods to use. This would keep the model and view separate, but feels dirty because then the HTML helper would become responsible for more than just building the HTML.
Is this a reasonable situation to break the separation of concerns as designed by MVC or is there a more appropriate solution?
Since you are using MVC3, I would recommend using child actions for the sub fields:
http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx
Child actions allow you to execute an action on a controller inside of your view, this would be a much cleaner approach.