Aspect Oriented Programming In MVC

Aspect Oriented Programming In MVC

Sit back and relax.  We are going to get technical.  Ready?  Much like recursion, Aspect Oriented Programming is a programming paradigm for solving problems from a different perspective. The goal of this approach is to create reusable code which solves solution-wide concerns. The end result of investments in Aspect Oriented Programming are usually large dividends due to the opportunity for code reuse. Let’s examine the concept and develop an example.

Aspect Oriented Programming 101

By now most developers have already seen an introduction to MVC and during any introduction, you will quickly begin to see the links between Aspect Oriented Programming and ASP.NET MVC.

If you haven’t had the opportunity to view an intro to MVC I recommend the free introductory training videos on the ASP.NET website.  http://www.asp.net/mvc

The first example you will probably notice is data annotations you add to your data model.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace MvcApplication1.Models
{
    public class Product
    {
        public int Id { get; set; }

        [Required]
        [StringLength(10)]
        public string Name { get; set; }

        [Required]
        public string Description { get; set; }

        [DisplayName("Price")]
        [Required]
        [RegularExpression(@"^$?d+(.(d{2}))?$")]
        public decimal UnitPrice { get; set; }
    }
}

In this example “[StringLength(10)]” is a data annotation applied as an attribute to the Name property. The really cool thing about these attributes is that they centralize what we know about products and make them more reusable. Now, when we use this model to make a “Create Product” page this attribute will be used. The same attribute will be used on the “Edit Product” page and everywhere else that references the model and as such we only have one place to maintain the proper length for Names of products. Additionally, this information will be sent to the user in the HTML form. When the Razor view engine sees this attribute it will modify the textbox used for editing this data to include the max length validation. Afterwards, the same logic will be used to determine if the object is valid when we inspect the ModelState.IsValid property.

This example showcases the ability to make a decision once and reuse it across the entire project. In other descriptions, you’ll hear that Aspect Oriented Programming is a means to solve “cross-cutting concerns” and this type of solution-wide application of logic is what that statement describes. In addition to data validation, we see here that labels for properties are another cross-cutting concern. Another good example built into MVC is the [Authorize] attribute used to make sure your users have been authenticated before they are allowed to view sections of your site.

Another solution-wide problem developers deal with is performance. Knowing that this is something we care about across the entire project tells us that Aspect Oriented Programming can be a practical approach to this challenge.

public class Log4NetProfileAttribute : ActionFilterAttribute
{
    private Stopwatch swatch;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        swatch = Stopwatch.StartNew();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        swatch.Stop();

        Type controllerType = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType;
        ILog log = LogManager.GetLogger(controllerType);
        log.Info(string.Format("Completed {0} action from {1} controller after {2} seconds",
            filterContext.ActionDescriptor.ActionName,
            filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
            swatch.Elapsed.TotalSeconds));

        base.OnActionExecuted(filterContext);
    }
}

This example consists of two main functional portions a stopwatch from the System.Diagnostics namespace and logging provided by Log4Net.

For a recap of setting up Log4Net see this previous article.

The bulk of the functionality is implemented by the parent class ActionFilterAttribute. As a child of this class, all we need to do is decide what we want to do before a controller action starts and perform our clean up after the controller action completes. Since we’re measuring performance I start up a Stopwatch and then record the elapsed time between the two events. To use this code we can now decorate any controller action in our project with the Log4NetProfileAttribute to receive performance metrics. Additionally, because it uses Log4Net we know that this performance measurement will only be captured whenever we use the INFO logging level.

        [Log4NetProfile]
        public ActionResult Index()
        {
            Random rand = new Random();
            //take a quick nap
            Thread.Sleep(rand.Next(10, 50) * 10);
            return View();
        }

Two things to call out in this example. You will need to use the square brackets, just as we did with the annotations, and you do not include the “Attribute” portion of the class name.

Data validation and user authorization are the two most common areas where Aspect-Oriented Programming can provide a better separation of logic for code reuse but adding it to your toolbox will certainly make some challenges easier to conquer.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Like what you've read? Please spread the word!

Leave a Reply

Your email address will not be published. Required fields are marked *