Saturday, September 15, 2012

Best Practices for ASP.NET MVC 3 - Model Suggestions

This blog post presents a set of coding guiding principle intended at helping the ASP.NET MVC developer build concrete applications. Of course, it's up to you as the developer to choose which of these guiding principles are suitable for your application

Model Suggestions


The model is where the domain-specific objects are defined. These definitions should include business logic (how objects behave and relate), validation logic (what is a valid value for a given object), data logic (how data objects are persisted) and session logic (tracking user state for the application).

DO split the model its own project with a separate assembly.

For applications with a large complex model, it's a good initiative to create a separate assembly for the model to avoid accidentally mixing concerns. You can then reference the model assembly in your ASP.NET MVC project

DO place all business logic in the model.

If you put all business logic in the model, you protect the view and controller from making business decisions concerning data. You also harvest the following profits
  • Fewer duplicated business logic
  • The view is easier to read when there is no business logic present
  • Testing business rules is out-of-the-way to the model
For example, if you have a business requirement to display a user's full name, you could put the logic in the view as follows
@if (String.CompareOrdinal((string)TempData["displayFullName"], "on") == 0)
    { 
        <text>Model.firstName, Model.lastName</text>
    }
    else
    {
       <text> Model.firstName</text> 
    } 
However, you would have to duplicate this logic in every place this business requirement was needed. Instead, you could put the business logic in the “display Full Name " rule in the model by adding a property to the model that encapsulates the business logic as follows
public string combinedName
{
   get
   {
       return (displayFullName ? firstName + " " + lastName : firstName);
   }
   private set
   {
      ;
   }
}
This would greatly simplify the view as shown
<p>Welcome,  @Model.combinedName</p>

DO place all validation logic in the model

All input validation should occur in the model layer. This includes client side validation, which is essential to performance. However, client side validation can be circumvented (with, for example, tools like Fiddler)
You can use ModelState to add validation checking. The following example shows how to add validation checks to ModelState explicitly
if (String.IsNullOrEmpty(pageName))
{
   ModelState.AddModelError("pageName", Resources.AddPage.PageNameError);
}  

Nevertheless, given the advances in .NET Framework, the System.ComponentModel.DataAnnotations should be the favored method for validation. These annotations are added as attributes to the properties of a model class, as the following example shows
public class Page
{
   [Required(ErrorMessageResourceName = "nameRequired", ErrorMessageResourceType = typeof(Resources.Page))]
   public String pageName { get; set; }
       ...
}


DO define interfaces for data access

It is favored that interfaces be used to expose methods on a provider for data access. This strengthens the loosely coupled component design of ASP.NET MVC.
Consider using the Entity Framework or LINQ to SQL as the means of creating wrappers around calls to a database. Both Entity Framework and LINQ to SQL allow the use of stored procedures as well

DO place all session logic in the model.

It is outside the scope of this blog discussion to travel around in depth the different mechanisms for storing session state in the model. As a starting point, here are a few of possibilities of session state storage:
  • In Process
    • Strengths : No extra setup needed.
    • Weaknesses : Does not work if the web site needs to balance
  • Session State Service
    • Strengths : Lightweight service runs on each machine in a web farm. Faster than database session storage
    • Weaknesses : Session data is lost if the service goes down
  • Database
    • Strengths : Session data is persisted
    • Weaknesses : Slower than session state, Management cost is relatively high
In Next Blog Post, I'll discuss on View Suggestions
Happy Coding!!

1 comment: