Click here to monitor SSC
  • Av rating:
  • Total votes: 10
  • Total comments: 0
Dino Esposito

Aspect-oriented Programming and Code Contracts in ASP.NET MVC

31 October 2013

There are some aspects to application programming, such as logging, tracing, profiling, authentication and authorization that cut across the business objects. These are difficult to deal with in an object-oriented paradigm  without resorting to code-injection, code-duplication or interdependencies. In ASP.NET MVC, you can use attributes in the form of action filters to provide a neater way of implementing these cross-cutting concerns.

Object-orientation is the predominant programming paradigm nowadays: It is mature and well-understood by most developers. Although it had been well-known since the seventies, it reached the mainstream after Bjarne Stroustrup added the concept of “objects” to the C language to get more powerful tools to represent the behavior of entities. It was definitely a revolutionary approach. However, as soon as object-oriented programming (OOP) started gaining momentum and began to be widely used in projects, developers spotted immediately an inherent, almost structural, problem.

OOP works in business enterprises by mapping identified business entities and relationships to classes, adding polymorphism and encapsulation and, overall, promoting code reuse. OOP is then quite good at describing business processes through components and therefore at dealing with the concerns associated with an entity and its software counterpart—the class. Where OOP inherently fails is at dealing with cross-cutting concerns.

Agreed, probably the term “fail” is misplaced here and exaggerated. But for sure OOP is not as good with cross-cutting concerns as it is with modeling. Developers then started the quest for better techniques consistent with the OOP paradigm to deal with this, and prevent the need for code-injection, code-duplication or interdependencies.

The Problem of Cross-cutting Concerns

A cross-cutting concern, by definition, affects not just a given family of classes but many classes in a system. Common examples of cross-cutting concerns are logging, tracing, profiling but also authentication and authorization, error handling and application-wide caching and pooling. In plain OOP practice, nearly every class requires injections of code to address cross-cutting concerns. In real-world-size projects, this amount of extra code may become significant, and the practice of duplicating it across various classes becomes less attractive, although unavoidable.

At the foundation of OOP is the principle that every class should do one and only one thing. At the foundation of real-world software, though, is the fact that cross-cutting concerns should be properly dealt with. Doing so, however, often requires plenty of repetitive, admin-style code for things like logging, tracing, error handling, pooling, threading, and so forth. In the end, implementation of concerns is usually either based on boilerplate code cut-and-pasted from other projects or totally left out.

Already in the mid-1990s, aspects were introduced as a way to wrap cross-cutting concerns into separate code that could be managed, tested and debugged individually before being applied to target methods at run time. Aspect-oriented programming (AOP) never really took off, but flavors of it reformulated as attributes are to be found in a variety of frameworks. You find aspects, for example, in Microsoft Unity and in IoC containers. In ASP.NET MVC, action filters expressed as attributes are just another form of aspects because they add extra behavior and logic to the pre- and post-execution phase of controller methods.

Action Filters as Aspects

Implemented as an attribute, an action filter provides a declarative means to attach some behavior to a controller’s action method. By writing an action filter, you can hook up the execution pipeline of an action method and adapt it to your needs. In this way, you also remove any logic from the controller class that doesn‘t strictly belong to the logic of controller methods. In doing so, you also make this particular behavior reusable and, more importantly, optional.

In ASP.NET MVC, action filters are ideal for implementing solutions to cross-cutting concerns that affect the life of your controllers. A canonical example of an action filter is, in fact, the Authorize attribute to attach an authentication filter to any marked method; another good example is the Exception action filter aimed at providing a centralized way to capture and handle exceptions originated by controller methods.

Conceptually speaking, action filters are very similar to aspects. When you create action filters, you can indicate whether the specific action should take place before and/or after the method. An action filter is a class that implements the IActionFilter attribute, as described below.

public interface IActionFilter
{ 
   void OnActionExecuted(ActionExecutedContext filterContext); 
   void OnActionExecuting(ActionExecutingContext filterContext);
}

The two methods just let you indicate which code runs before and after the controller method. The ASP.NET MVC framework comes with a long list of predefined, built-in filters; others can be found in open-source projects such as latest MvcMate at http://mvcmate.codeplex.com.

Validation by Contract

In ASP.NET MVC, each request ends up being mapped to a controller method. Each controller method has its own signature and a bit of business logic that makes it accept, say, only certain values of a given type. How would you verify that only correct values are being passed?

Let me put the question the other way around. If an invalid value is passed, what should be the behavior of the method? Should it just proceed as far as possible and likely crash at some point? Should it just log the invalid parameter and return or throw?

Preliminary validation of input parameters is a fundamental aspect of coding. It is so essential and vital for code to be really close to common sense; but just as common sense it is sometimes not so common. This observation brought Bertrand Meyer to formalize a software correctness methodology named Design-by-Contract. Design-by-Contract is based on the idea that each software module should have a contract that formally describes what comes in and what comes out of the method.

Today, Design-by-Contract is implemented in C# through a relatively little known feature—Code Contracts. In .NET, Code Contracts use preconditions to assert preliminary conditions to be verified for the method to run. Code Contracts also use postconditions to assert conditions determined by the execution of a piece of the method. In a way, Code Contracts add a light aspect-oriented flavor to .NET code because it makes it easier to define parameter validation using a syntax that, although not attribute-based, is at least conceived as assertions.

Inside Code Contracts

.NET Code Contracts are formed by three main types of contracts: preconditions, postconditions and invariants. Of the three, I reckon that preconditions are the most important contract and the most commonly used one. Postconditions and invariants come more into play as you progress towards the building of a true and full-fledged domain model. Preconditions are instead a more basic type of contract largely equivalent to the If-Then-Throw pattern. For this reason, they tend to be quite common.

The If-Then-Throw pattern suggests you place a barrier of conditional statements at the very beginning of each method, possibly in any class you write. Each conditional statement ensures that a Boolean condition based on input values hold true. If the condition is not verified, then the code throws an exception.

Preconditions have the same functional effect as an implementation of the If-Then-Throw pattern except that preconditions require you express the condition as it is required to be and not its negation. For example, suppose you have a method that gets an integer and the integer is expected to be greater than zero. Here’s how you would write the method using the If-Then-Throw pattern:

public ActionResult Increment(Int32 value)
{ 
   if (value <=0) 
      throw new InvalidArgumentException(); 
   :
}

Here’s instead how to rewrite it using precondition contracts in .NET:

public ActionResult Increment(Int32 value)
{ 
   Contract.Requires<InvalidArgumentException>(value >0); 
   :
}

Code contracts must be specified in the body of methods and inserted via plain code. The class Contract defined in the System.Diagnostics namespace exposes a bunch of static methods, one for each type of contract. According to the team, the choice of having developers use plain code rather than attributes was made with the precise purpose of keeping contracts to a declarative level but more flexible than with .NET attributes.

At a quick comparison, the code based on If-Then-Throw expresses the condition in its negated form; the precondition format instead tells you explicitly about the required condition: value >0. This means that contracts also work well as documentation for unit testers and other developers. At any time, in fact, the conditions expected on parameters can be consulted in their positive form.

By also adding postconditions, you end up having a clear set of statements at the beginning of each method that show what’s required for the method to operate and what’s going to be produced at the end of the work. It’s the x-ray of the method; you can learn all of it from a single place.

Contracts in ASP.NET MVC Code

As you might imagine, Code Contracts are not specific to ASP.NET MVC, but are rather a fairly generic API that works with any type of .NET application. However, in ASP.NET MVC you certainly need to add a validation layer within controllers; By using contracts, the code stays succinct and clear and keeps the noise of if statements to a bare minimum. Moreover, this guarantees that, if invalid parameters are passed, then the API can capture them and throw appropriately.

Sometimes you might want to distinguish situations in which patently wrong values are passed as parameters and situations in which parameters are omitted. In the latter case, you can use valid default values in the signature to ensure that if the parameter is left empty then valid values are set anyway.

When it comes to precondition contracts, you can choose between two forms ofRequires statements: regular and generic. A generic Requires<TException> contract just throws the specified exception if the contract is not fulfilled. A regular Requirescontract, instead, fires an API specific exception—the ContractException exception. You can catch contract exceptions by registering an event handler for the ContractFailed event. Here’s how to set it:

Contract.ContractFailed += (YourExceptionHandler);

The exception handler looks like the one shown below:

static void Contract_ContractFailed(Object sender, ContractFailedEventArgs e)
{ 
   ...
}

It is also worth noting that regular Requires statements are omitted when the project is configured in debug mode. This point introduces, however, a subtle point about contracts that needs be explored further.

Implementation of Code Contracts in .NET

To use Code Contracts, you reference System.Diagnostics and start using the Contract class in your code with all of its static methods. Interestingly, if you just compile and run the code—without doing anything else around the project—it brilliantly fails and throws an exception. Using .NET Reflector, you can see the following code in the Requires<T> method (and in all other methods on the Contract class):

public static void Requires<TException>(bool condition) where TException : Exception
{ 
   Contract.AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
}

If this is how the Requires<T> method is implemented, how is that it actually works? The key is the rewriter. Code Contracts require the use of an external tool—the rewriter—which runs after the compiler and rehashes bytecode so that any code required by preconditions and postconditions is inserted where it belongs. Without the rewriter, Code Contracts will be an empty box.

At the moment, the rewriter is not part of the .NET Framework—a very debatable decision. You have to download it separately as a Visual Studio extension from http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970. The rewriter should also be explicitly enabled from the project property pages, as shown in Figure 1.

Enabling Code Contracts

Figure 1. Enabling Code Contracts runtime checking in Visual Studio.

Note that, depending on which Requires syntax you opt for, you may also be asked to tweak the default Code Contracts settings. For example, if you opt for Requires<T> then you also need to change the value of the Assembly Mode parameter in Figure 1.

Final Thoughts on Aspects

I started this article with a mention of aspect-oriented programming and its impact on mainstream object-orientation. The problem of the most effective way of adding aspects to OOP is still open. In the .NET space, there are two main routes: attributes and filters injected by IoC frameworks (e.g., Unity). In ASP.NET MVC, you can use attributes in the form of action filters to wrap the execution of a controller method between a pre- and/or post-execute method. What the filter does just adds aspects to the controller method without impacting its structural business logic.

Code Contracts are another form of aspects that targets specifically the realm of parameter validation and code correctness. Child of the Design-by-Contract philosophy, Code Contracts in .NET come as ad hoc code injected at compile time. When you read back the code, though, you find in your source code only a bunch of declarations about what’s required and what’s ensured. It all look like assertions, but the effect is far deeper and preserve significantly readability.

Dino Esposito

Author profile:

A long-time trainer and consultant, Dino is the author of many popular books for Microsoft Press for .NET developers.including “Architecting Mobile Solutions for the Enterprise“ and “Programming ASP.NET MVC” both for Microsoft Press. CTO of Crionet, a firm specializing in Web-based and mobile solutions for sport events across Europe (http://www.crionet.com), at the moment Dino is also technical evangelist for JetBrains, where he focuses on Android and Kotlin development, and member of the team that manages WURFL—the database of mobile devices used by organizations such as Google and Facebook. Follow Dino through his blog at http://software2cents.wordpress.com or at http://twitter.com/despos

Search for other articles by Dino Esposito

Rate this article:   Avg rating: from a total of 10 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.
 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.