Model: The “M” in ASP.NET MVC

Modeling Data for an ASP.NET MVC Application

Dino Esposito

October 30, 2009

10 Min Read
ITPro Today logo

CoreCoder

LANGUAGES: C#

ASP.NET VERSIONS: 3.5 | MVC

Model: The M in ASP.NET MVC

Modeling Data for an ASP.NET MVC Application

By DinoEsposito

According to the original formulation of the MVCpattern, the model is the object that represents the application gateway to thebusiness logic. The model holds the current state of the application and repliesto requests for state changes coming from the view via user gestures. The modelalso is designed to execute actions requested by the controller, which typicallyresults in state changes. In a nutshell, the model is the representation of anydata consumed by view and controllers. But what about the MVC pattern asimplemented in ASP.NET MVC?

Well, that s a slightly different thing. In ASP.NETyou find a version of MVC adapted to a new medium the web that just wasn taround yet at the time in which MVC was first devised (in the 1980s). In termsof patterns, ASP.NET MVC implements the Model2 pattern rather than the classicMVC. On the other hand, Model2 was developed as an attempt to bring MVC and itsseparation of concerns to the web. Figure 1 shows a UML sequence diagram of howthe Model2 pattern works (and subsequently ASP.NET MVC).

Figure 1:The sequence diagram for the Model2 pattern

What s the Model Really For?

There are a few differences between classic MVC andModel2. First and foremost, there s no direct contact, let alone an observerrelationship, between view and model. Second, the controller renders the viewand explicitly passes data to it. The user gesture is not captured and handledby the view as in classic MVC. In a web scenario, the browser captures theuser s activity and posts a request to the web server. On the server side, itis a system component the front controller that intercepts HTTP requests andfigures out from the URL and headers which controller will be in charge for therequest. From the server perspective, the entry point in the chain is thecontroller, not the view as is the case in classic MVC. Today, people oftenspeak of MVC with regard to the web, but what they actually mean (consciouslyor unconsciously) is Model2. And Model2 is exactly the pattern behindMicrosoft s ASP.NET MVC Framework.

So what s the M in ASP.NET MVC? At the end of theday, the model is any object the controller can talk to that triggers businessactions. Shape and color of the model depends on the architecture of yourback end and the layers you have in place. If you use LINQ to SQL or EntityFramework to drive data access, you might be led to think that model means anobject model. From a design perspective, this is incorrect. The model isprimarily the gateway to the business logic.

The business logic is then made of business objects(including services, workflows, and ad hoc components) and an object model. Theobject model can be a collection of typed DataSets or, better yet, a LINQ toSQL or an Entity Framework object model. It also can be something different,such as a handcrafted hierarchy of plain .NET classes.

If the model is based on typed DataSets, then youneed to write your own objects to manage persistence and perform calculations.If you opt for LINQ to SQL or Entity Framework, you can kill two birds with asingle stone: You have an object-based representation of the data and a gatewayobject to call it the DataContext object in LINQ to SQL and the ObjectContextobject in Entity Framework. In these cases, the underlying framework offers tomanage persistence via its internal O/RM engine. The model , however, also canbe based on a Service Layer pattern and manage persistence via any O/RM in themarketplace, including NHibernate and Genome. The model also can bearticulated as a set of CSLA.NET business classes, as well as in a variety ofother ways.

The model in modern MVC frameworks, however, is notsimply a library of classes to describe the data being used. It is, instead, alayer of code that contains data to work with and behavior to be invoked bycontrollers.

In the rest of this article I ll focus on thecharacteristics of the model that represents the data, assuming you haveanother layer that cares about persistence. (This is a common scenario when youopt for a solution based on LINQ to SQL or Entity Framework.)

Validation in the Data Model

A data model for a layered application has threemain requirements. It must expose a public interface for the data; it mustprovide a way to validate any instance of data; and it must publish an API towork with data and persist it. Persistence depends on the helper framework youuse. Data modeling depends on the approach you take in design. It can be adatabase-centric approach, where you start designing your data classes fromsome existing database. It also can be a data-centric approach, where youdesign your classes in a persistence-agnostic manner and delegate persistenceto a separate data access layer based on some O/RM tools.

What about validation, instead? Figure 2 shows thestructure of a sample class to be used as the root of an object model thatsupports validation.

public class MyRootObject : ISupportValidation

{

public virtual boolIsValid

{

get

{

try

{

return newValidationResults().IsValid;

}

catch

{

return false;

}

}

}

ValidationResults ISupportValidation.Validate()

{

ValidationResultserrors =

new ValidationResults();

:

return errors;

}

}

Figure 2:Validation in a data model

The ISupportValidation interface looks like this:

interface ISupportValidation

{

bool IsValid{get;}

ValidationResultsValidate();

}

ValidationResults is the class in your businesslogic responsible for reading and applying validation rules. Validation rulescan be defined in a number of ways, and are checked by the business logic. Forexample, you can develop your own validation block where you use attributes onmembers to define rules. Here s a quick example:

public class Customer : MyRootObject

{

public Customer()

{

:

}

[NotNullConstraint(Message="CustomerID cannot

be null")]

[LengthConstraint(5, 5,Message="Customer ID must be

exactly 5 charslong")]

public virtual string ID{ get; set; }

:

}

Attributes are part of the validation block and arechecked within the Validate method. Each attribute expresses a business rule.In the previous example, the Customer ID is set to be non-null and exactly fivecharacters long. In Microsoft s Enterprise Library 4.1, you ll find similarattributes and a ValidationResults class as used in this pseudo-code. Inparticular, you express business rules in Enterprise Library using attributessuch as NotNullValidator, StringLengthValidator, RegexValidator, and so forth.

The responsibility of validating the state of anobject definitely belongs to the business layer and precisely to objects thatyou use to perform operations. In no way does this responsibility belong to thepresentation logic.

Connecting the Validation Layer and Controllers

In ASP.NET MVC, the controller scripts the application sback end and object model in order to obtain the data it needs to display in anew or updated view. So it is the controller that validates objects from themodel before proceeding with operations. Here s a sample schema to follow:

// Controller method invoked from the UI
public class ProductController : Controller
{
public ActionResult Insert(Product p)

{

if (p.IsValid())
{

// Add product tothe storage

}

}
}

Any data the controller obtains from the model isthen serialized to the view so a fresh HTML page can be arranged. Likewise, thecontroller manages exceptions within the model, including business actions:

// Controller method invoked from the UI
public class ProductController : Controller
{
public ActionResult Insert(Product p)

{

try {

:

} catch {

:
}

}
}

In case of exceptions, it is up to the specificimplementation of the controller to decide whether the native exception fromthe model should be managed so that the user interface doesn t even know aboutthat and degrades gracefully with the empty data it receives. There s a moregeneral alternative, though. It is based on the assumption that the controllerswallows the original exception and replaces that with another exception thatthe view will handle. In ASP.NET MVC, however, the view is a sort of templateprocessed by a view engine that receives data and fills it in. It s hard tohandle exceptions at the view level. The controller is, ultimately, responsiblefor any exceptions raised within the model.

Validation in a LINQ to SQL Scenario

If you ever used LINQ to SQL to create the objectmodel for your ASP.NET MVC application, you know that the model is created by awizard. You certainly can put your hands on the generated file, but at the riskof losing any changes as you happen to restart the wizard. For this reason,classes in the LINQ to SQL model are partial. In this way, you can add yourchanges to additional partial classes and make them survive future changes madethrough the wizard.

One of the key changes you might want to make toLINQ to SQL classes relates to validation. LINQ to SQL classes are plain .NETobjects with no dependency on the framework. First and foremost, properties ofany classes in the model are annotated with rules inferred from the databaseschema. This means, for example, that data types are matched and nullability ishandled properly. Likewise, columns with unique values are honored.

In addition, classes within the model feature anumber of extensibility methods, namely partial methods that may, or may not,be implemented in some partial class. Many of these methods regard validation.Here s an example:

[Table(Name="dbo.Customers")]

public partial class Customer : INotifyPropertyChanging,

INotifyPropertyChanged

{

partial voidOnValidate(System.Data.Linq.ChangeAction

action);

partial voidOnCustomerIDChanging(string value);

partial voidOnCustomerIDChanged();

partial voidOnCompanyNameChanging(string value);

partial void OnCompanyNameChanged();

:

}

For each property in the class the wizard defines apair of partial methods of the type OnXxxChanging and OnXxxChanged, where Xxxis the property name. These properties are automatically called from the setterof each property and provide an effective way for ensuring that no invalidvalues are assigned:

public partial class Customer

{

partial voidOnCustomerIDChanging(string value)

{

if(value.Equals("KOEN2"))

{

throw newInvalidExpressionException("...");

}

}

}

The OnValidate method, instead, is a placeholderfor you to define when you re looking for just one method to call to ensurethat the object is valid.

Integrating Business Rules

Extensibility methods are not enough. They help youin preventing situations where code attempts to store invalid values intoproperties but don t support you much when it comes to business rules. Abusiness rule is not simply a syntax rule and does not necessarily apply tojust one property. It is recommended that you further decorate your LINQ to SQLclasses with attributes or code that express and validate business rules. Apossibility is defining a validation interface such as the aforementionedISupportValidation and using partial classes to force it in any LINQ to SQLentity class.

The Validate method will then go through the listof checks necessary for each entity and report violations to the caller code.Here s a possible schema for a solution:

public ValidationResults Validate()

{

ValidationResults openPoints=

new ValidationResults();

if ( ... )

{

string message ="...";

openPoints.Add( newViolation( message );
}

:

}

Such a Validate method, or whatever name you wantto give it, will be called from the code before persisting the object or, ingeneral, at any time in which the validity of the object has to be checked.

Conclusion

Originally formulated to cover the creation of theentire application, the MVC pattern has been adapted to the web and fullyimplemented in the ASP.NET MVC Framework. The model in the pattern representsthe gateway to the back end of the system, as well as any exposed businessactions. At the same time, the model also incorporates the representation ofthe data within the application.

ASP.NET MVC doesn t mandate any specific approachor technology to build the model and add validation to it. So you can use LINQto SQL s built-in facilities to implement syntax checks such as nullability anddata types. At the same time, you can use extensibility methods to checkbusiness rules or you can integrate your own business validation layer on topof LINQ to SQL classes. The business validation layer can be created viaEnterprise Library or it can be your own library. The freedom of implementationis unmatched; but make sure you don t overlook a layer to validate your MVCmodel.

Dino Esposito ([email protected]) is an architect at IDesign,specializing in ASP.NET, AJAX, and RIA solutions. Dino co-authored Microsoft .NET: Architecting Applications for the Enterprise and Microsoft ASP.NET and AJAX: Architecting Web Applications.

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like