Design Patterns – How Business Rules Affect Presentation in MVC

asp.net-mvcdesign-patterns

The MVC design pattern is supposed to led itself to separating business rules from presentation.

But sometimes business rules AFFECT presentation. What is the best way to deal with this? Is that when a ViewModel should be used?

For example, going back to my non-existent Library application, a librarian is scanning returned books. The system indicates that a book is late, and applies a fine to that patron.

Certain employees may have security to override that fine based on certain conditions.

The presentation layer of my library application will need to let the employee set the fine to 0, or click a button to override the fine.

But employees who do NOT have security to do this should see the fee as either a disabled input or maybe read only.

Note that security may not be the only business rule. This is just an example. For example, my application may have configuration information set up somewhere that causes a field on a screen to become unnecessary, etc.

While the code could just let anyone change the fine and then show a validation message, that's not a good user experience.

What is a good practice to accomplish this? The options I can think of (using ASP.NET MVC) are:

  1. Have the view itself check the business rule and disable or enable the field.

  2. Use a HTMLHelper function that implements the presentation for the fine field, and have that helper function check the business rule.

  3. Have the controller check the business rule and use a different view.

  4. Have the controller check the business rule and set a property in the ViewBag that indicates whether the field is enabled.

  5. Use a ViewModel checks the business rule and set information indicating that the field is enabled.

Options 1 & 2 cause the presentation layer to have to do business rule validation, and that muddles things.

Option 3 will cause duplication of effort in that now you have two views defined.

Option 4 & 5 requires the presentation layer to know that the field COULD be enabled or disabled, but not WHY. I think I like 4 or 5 best.

Our there other options I'm not thinking of?

Best Answer

I think your option number 5 is best, but with some slight tweaking:

Your ViewModel should have a property that indicates whether the data can be updated, or not. Perhaps a "CanOverrideLateFine" boolean property.

Whatever is creating the ViewModel (your Controller, or more likely a business service that your Controller delegates to) is responsible for evaluating the business rules and setting that property. Not the ViewModel itself.

The View will then inspect the "CanOverride" property and determine how to properly render for the user. It may be as simple as enabling or disabling a form field, but it may be something completely different (maybe not even rendering the field, or supplying a completely different visual element).

Related Topic