How we do ASP.NET MVC


Sample MVC Solution

In this post I will show a sample ASP.NET MVC 2.0 project structure illustrating different concepts such as data access, user input validation and mapping between the domain and the view model. The project is still under construction but the source code is available at github.

I will illustrate the usage of the following frameworks:

  • MvcContrib bringing useful extension methods and strongly typed helpers to ASP.NET MVC
  • AutoMapper enabling easy mapping between the domain and the view models
  • FluentValidation – a small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects
  • NHibernate – a popular ORM in the .NET world
  • FluentNHibernate – a statically compiled alternative to NHibernate’s standard hbm xml mapping
  • Spring.NET – object container and dependency Injection framework for .NET
  • Rhino.Mocks – A dynamic mock object framework for the .Net platform. It’s purpose is to ease testing by allowing the developer to create mock implementations of custom objects and verify the interactions using unit testing

 

Armed with this arsenal of frameworks let’s start exploring the solution structure. I’ve opted for 2 projects solution but in many real world applications more levels of abstraction could be brought to the business layer. Personally I favor to have less big assemblies rather than many small assemblies into the solution. Fewer the assemblies, faster the load time and faster the IDE. In this case particular attention should be brought to bring proper separation of concerns inside the same assembly

project_structure

 

The domain consists of a single User class and a repository interface defining the different operations on this model:

Domain

 

Mapping

The next step is to define the mapping between our domain and a relational model expressed in a fluent manner:

 

And here’s the implementation of the repository:

HibernateDaoSupport is a base class defined by the Spring Framework managing SQL transactions and NHibernate session.

Once we have implemented the data access layer we could move on to the web part. The application consists of a single RESTful UsersController allowing the standard CRUD operations with our users model. As all our views are strongly typed we shall define a view model for each view and a mapping between the domain model and this view model. In our simple case the view model will simply have the same structure as the domain model but in real world scenarios it will be a projection of the domain model for a particular view.

And the respective validator:

And mapper between the domain and view model:

This bidirectional mapper will be used by our RESTful controller:

Notice the AutoMapAttribute. This is a custom attribute allowing us to automatically convert the domain model retrieved by the repository to a view model and present it to the view:

The OnActionExecuted method will be called after each action method has finished executing and it will use the model passed to the view and convert it to the appropriate view model. It simply substitutes the ViewData.Model property with the appropriate view model to finally pass it to the view for rendering.

The controller follows the standard RESTful conventions for naming the action and the HTTP verbs:

URL

HTTP Verb

Action

Description

/users/index GET Index() return all users
/users/show/id GET Show(int id) return a specific user
/users/new GET New() return an HTML form for creating a new user
/users/create POST Create(UserViewModel userView) create a new user
/users/edit/id GET Edit(int id) return an HTML form for editing a specific user
/users/update PUT Update(UserViewModel userView) update a specific user
/users/destroy/id DELETE Destroy(int id) delete a specific user

Because most browsers support submitting HTML forms only using the GET and POST verbs, there’s the Html.HttpMethodOverride helper which generates a hidden field inside the form and is used by the routing engine to dispatch to the proper controller action.

Unit Tests

Unit testing our controller actions is essential. I’ve been using the excellent MVCContrib.TestHelper in conjunction with the Rhino.Mocks framework to test controllers in isolation by mocking the HTTP context. Here’s how the test logic looks like:

Views

And the last but not least part of the picture are the views:

Index.aspx

TableLinks.ascx

Edit.aspx

New.aspx

UserViewModel.ascx editor Template

A very important aspect of the views is that they are all strongly typed to a view model and use only strongly typed helpers, even for generating the links. One day when Visual Studio becomes power enough you will be able to seamlessly refactor/rename a property without worrying about all those magic strings.

Further enchantments will include adding client side validation using the jQuery validate plugin in order to improve the user experience and preserve bandwidth.

Leave a Comment

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">