Separation of Responsibilities with MVC

Recently I have been working on a new pattern with ASP .NET MVC, based mainly on what I have learned from MVVm and other patterns.  That said, I dont know if I can really call this new, mainly because it really is an amalgamation of patterns working together to keep the architecture clean.

Step 1: The Controller Architecture
As with any system enforcement of DRY (Don’t Repeat Yourself) is essential.  This can be achieved any number of ways, though the most common way is the abstraction of what is repeated into a separate layer, to that end we introduce the BaseController class.

public abstract class BaseController : Controller
{
     protected ServiceController CurrentServiceController
     {
          get; private set;
     }

     public void InitalizeServiceController()
     {
          CurrentServiceController =
               ServiceController.CreateNewServiceController();
     }
     
     public void DestroyServiceController()
     {
          CurrentServiceController.Dispose();
     }
}

Some things to note here.  This class is inheriting from Controller which is provided by Microsoft and is the standard class which all ASP .NET MVC Controller derive from.  The two public methods we will get to later.

Step 2: Creating the Controller

ASP .NET MVC has many points of extensibility, and we will take advantage of two of them, the first one is how we “build” a controller.  Whenever a request is made, MVC must determine which controller to instantiate based on the same found in the request (http://www.yourmvcwebsite.com/Series/Edit/1).  Once it has this it will attempt to call the action.  The reason we need to do this is for our data layer.  This is a very simple instance where the Dependency Injection pattern is used, though we are choosing to not use a DI framework such as Ninject or StructureMap because our needs are simple.  The goal is to set the Context reference at creation and then dispose it at release.  We can achieve this by using what is already available and simply leverage basic inheritance.

public class AnimeControllerFactory : DefaultControllerFactory
{
     public override IController CreateController(
          RequestContext requestContext,
          string controllerName
     )
     {
          IController controller = base.
               CreateController(requestContext, controllerName);
          if (controller as BaseController != null)
          {
               ((BaseController)controller).InitalizeServiceController();
          }

          return controller;
     }

     public override void ReleaseController(IController controller)
     {
          if (controller as BaseController != null)
          {
               ((BaseController)controller).DestroyServiceController();
          }

          base.ReleaseController(controller);
     }
}

We could have used Reflection here to determine the type name string and then used Activator to actually get an instance, but why do that when MVC already does it for you.  Thus we call the overridden method, which will return to us an instance implementing IController, from there we can do some simple casting to get to BaseController.  We then call our methods which take care of the initialization process while continuing to remain unaware of what is happening.  This is key, if we were to simply make a call to new() we would be coupling the two projects together, we dont want to that in our ControllerFactory.

Step 3: The Data Access Layer

One of my goals with this architecture was to totally separate generated entities from DTOs.  To that end we create a “service” layer which performs the translation of a DTO to and from a Model.  (Note: I tend to call my generated classes models and my DTOs entities).  The following in an excerpt from the ServiceController class which acts as a “service store” for all services in the application and provides access to these services for all controllers via BaseController.

public class ServiceController : IDisposable
{
     private ServiceController()
     {
          CurrentEntityContext = new AnimeEntityContext();
     }
     
     private AnimeEntityContext CurrentEntityContext { get; set; }
     public static ServiceController CreateNewServiceController()
     {
          return new ServiceController();
     }

     #region Service References
     private SeriesService _seriesService;
     public SeriesService SeriesService
     {
          get
          {
               if (_seriesService == null)
                    _seriesService = ServiceFactory.
                         GetServiceReference(CurrentEntityContext);

               return _seriesService;
          }
     }
     #endregion

     public void Dispose()
     {
          CurrentEntityContext.Dispose();
     }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see we create a private property in this controller for the EntityContext (we are using Entity Framework for the curious).  To reduce the repetitive and monotonous nature of writing the code for instantiating each Service class, I created a base class ServiceBase and then a Factory class (ServiceFactory) which takes care, generically, of setting the underlying context for those providers.

public static class ServiceFactory
{
     public static T GetServiceReference(AnimeEntityContext context)
          where T : ServiceBase, new()
     {
          T returnObject = new T();
          returnObject.SetEntityContext(context);

          return returnObject;
     }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Step 4: The Model Binder

For the unaware, ASP .NET MVC permits a special type of parameter passing which analyzes a form collection and assigns properties based on name to an object of a given type. This instance is then passed to the action.  In a previous post, it was discussed how to do this – please visit http://www.jfarrell.net/2009/10/experiments-with-asp-net-mvc-model.html

Step 5: Validation of Models

One of the most monotonous tasks of any web application is validation.  As developers we cant always understand why users do what they do, but we do know we have to guard against it.  How many times have you made pages which touch the same object, thus you have to violate “DRY” and you pay for it later when something changes and you forget one of the spots.

Recently one of the new ways of enforcing validation is by annotating the objects, what I mean by that is the use of attributes to describe what kind of values a property can hold.  You will find these in the System.ComponentModel.DataAnnotations namespace (look for v3.5) as part of MVC 2.  The following is an example of decorating a class to enforce validation.

public class SeriesEntity : IEntity
{
     // simple data references
     public int SeriesId { get; set; }

     [Required(ErrorMessage = "Series name is required")]
     public string Name { get; set; }
        
     public bool IsActive { get; set; }

     // complex data references
     public IList Seasons { get; set; }
     
     [CollectionLength(1, ErrorMessage = "At least one Genre must be selected")]
     public IList Genres { get; set; }
     public StudioEntity Studio { get; set; }
}
Note: CollectionLength is a non-standard validation attribute

Validation takes place in the Model Binder, so we will return to the custom model binder from the referenced blog post. The OnPropertyValidating method is called for each property the binder is called to bind, thus we need to have its value first, hence the previous post will explain how to accomplish this.

protected override bool OnPropertyValidating(
     ControllerContext controllerContext,
     ModelBindingContext bindingContext,
     PropertyDescriptor propertyDescriptor,
     object value)
{
     var validationAttributes = bindingContext.Model.GetType().
          GetProperty(propertyDescriptor.Name).GetCustomAttributes(false).
          OfType();
     foreach (var validationAttribute in validationAttributes)
     {
          bool result = validationAttribute.IsValid(bindingContext.Model.
               GetType().GetProperty(propertyDescriptor.Name).
               GetValue(bindingContext.Model, null));

          if (!result)
          {
               bindingContext.ModelState.AddModelError(
                    propertyDescriptor.Name, validationAttribute.ErrorMessage);
               return false;
          }
     }
     return true;
}

Something that I noticed working with the standard binder is that it tends ignore properties containing complex types.  That is if you had an array of type Genre, so Genre[], it would not bind because of Genre.  If you instead made it int[] and gave it an array of GenreId values, it would work just fine.  But I wanted to take things one step further and have my entity comeback mostly complete and not have extra properties just to support the binder.  Further, I wanted to be able to validate things, hence the reason for my custom validation attribute CollectionLength.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

public class CollectionLengthAttribute : ValidationAttribute
{
     private int MinLength = 0;
     private int MaxLength = int.MaxValue;

     public CollectionLengthAttribute(int minlength)
     {
          MinLength = minlength;
          MaxLength = int.MaxValue;
     }

     public CollectionLengthAttribute(int minlength, int maxlength)
     {
          MinLength = minlength;
          MaxLength = maxlength;
     }

     public override bool IsValid(object value)
     {
          if (value != null)
          {
               var collection = value as IList;
               if (collection != null)
               {
                    return collection.Count > MinLength
                         && collection.Count <= MaxLength;
               }
           }
           return false;
     }
}

Conclusion:

The idea behind this pattern is separate things in a very thread safe sort of way, also to unify the context being used as well remain highly testable.  In addition, we want to reduce dependencies and the use of reflection.  Reflection is an expensive operation that we don’t want to do more then we have to.  By using DefaultControllerFactory we are able to rely on what already exists.  This action alone reduces the amount of foreign dependencies (interfaces, base classes) we need to get our code to work.  We have two assets that are used for this purpose IEntity and BaseController.

The next piece to this is how to structure the controllers themselves and how to get the data from the DTOs to the Views in a structured way such that type safety is preserved and we refrain from duplicating as much as possible.  That post will follow early next week.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s