Use specific return types in your ASP.NET MVC action methods

Wednesday, 1 July 2009 19:00 by bengtbe

When looking at ASP.NET MVC examples on the web almost all action methods return ActionResult, even methods that could return a specific subclass. Here is an example from the NerdDinner source code: 

public ActionResult Index(int? page)

{

    const int pageSize = 25;

 

    var upcoming = dinnerRepository.FindUpcomingDinners();

    var paginated = new PaginatedList<Dinner>(upcoming, page ?? 0, pageSize);

 

    return View(paginated);

}

This method always returns a ViewResult, still they declare the return type as the ActionResult base class. This practice often leads to test code like the following:

ViewResult result = controller.Index(0) as ViewResult;

Assert.IsNotNull(result, "Controller should return a ViewResult");

 
In NerdDinner they even have a whole test just to make sure that the result is a ViewResult:
 

[TestMethod]

public void IndexAction_Should_Return_View()

{

    // Arrange

    var controller = CreateDinnersControllerAs("robcon");

 

    // Act

    var result = controller.Index(0);

 

    // Assert

    Assert.IsInstanceOfType(result, typeof(ViewResult));

}

 
All this testing code are unnecessary, if you just let your action methods use specific return types, like shown below:
 

public ViewResult Index(int? page)

{

    const int pageSize = 25;

 

    var upcoming = dinnerRepository.FindUpcomingDinners();

    var paginated = new PaginatedList<Dinner>(upcoming, page ?? 0, pageSize);

 

    return View(paginated);

}

This also makes it immediately clear for people reading the code, what this action method returns.

The only time I would return ActionResult is when different paths of the action method returns different subclasses. In these cases, you should of course write tests that verify the return types of the different paths.

In the book Pro ASP.NET MVC Framework Steven Sanderson also recommends returning specific types. Take a look at the quote below:

"This action method specifically declares that it returns an instance of ViewResult. It would work just the same if instead the method return type was ActionResult (the base class for all action results). In fact, some ASP.NET MVC programmers declare all their action methods as returning a nonspecific ActionResult, even if they know for sure that it will always return one particular subclass. However, it's a well-established principle in object-oriented programming that methods should return the most specific type they can (as well as accepting the most general parameter types they can). Following this principle maximizes convenience and flexibility for code that calls your method, such as your unit tests."

BTW: This blog post is not meant to criticize the NerdDinner tutorial. It is a great free tutorial, and is probably one of the best ways to get introduced to the ASP.NET MVC framework :)

kick it on DotNetKicks.com

Shout it

Book review: NHibernate in Action

Thursday, 4 June 2009 19:39 by bengtbe

Authors: Pierre Henri Kuaté, Tobin Harris, Christian Bauer, and Gavin King
Publisher: Manning Publications Co.
Purchase:
Manning, Amazon.com, Amazon.co.uk

Introduction

As part of my goal to learn ORM and NHibernate I purchased the NHibernate in Action book from Manning Publications. Before I give my conclusion, let's start with a summary of the different chapters in the book.

1. Object/relation persistence in .NET

This chapter starts the first part of the book, called Discovering ORM with NHibernate. Discusses object persistence, and briefly compares different approaches: hand coding, DataSets, LINQ-to-SQL, NHibernate, and ADO.NET Entity Framework. Describes Object/Relational mapping (ORM), and how it is used to solve the Object/Relational mismatch.

2. Hello NHibernate

Guides you through the process of setting up a project, creating a domain model, setting up the database, creating mapping file, configuring NHibernate, and doing some basic CRUD operations. Takes a high level look at NHibernate, its architecture and how it is configured.

3. Writing and mapping classes

This chapter starts the second part of the book, called NHibernate deep dive. Describes the most common scenarios when mapping a domain model to the database, including important concepts, such as object identity, inheritance, associations, entities vs. value-types, fine-grained object models, and transparent persistence. Finally, it shows three inheritance mapping strategies; table per concrete class, table per class hierarchy, and table per subclass. Covers both XML-mapping and attribute mapping.

4. Working with persistent objects

Describes the three object states (persistent, detached, and transient) that domain models have in a NHibernate application, and how they move from one state to another. It also gives an overview of different ways to get objects out of the database.

5. Transactions, concurrency, and caching

Shows how NHibernate handles transactions, short vs. long conversations, optimistic concurrency control and versioning. Finally it discusses caching and describes the first- and second-level cache that NHibernate provides.

6. Advanced mapping concepts

Goes into detail of more advanced mapping techniques, covering mapping types, custom mapping types, nullable types, enumerated types, collection of value types, mapping of entity associations, and mapping of polymorphic associations. 

7. Retrieving objects efficiently

Describes object retrieval with both HQL, Query by Criteria, and native SQL. Topics covered are parameters, comparison operators, logical operators, ordering, joining, report queries, dynamic queries, and query optimization.

8. Developing NHibernate applications

This chapter starts the last part of the book, called NHibernate in the real world. Discusses N-tier development by going through the business, persistence, and presentation layer. Finally it shows how NHibernate can be used to implement audit logging.

9. Writing real-world domain models

Covers domain-model development processes and tools, legacy schema mapping, understanding persistence ignorance, implementing business logic, data binding entities in the GUI, and filling DataSets from entities.

10. Architectural patterns for persistence

Focuses on the design of the persistence layer. Covers designing the persistence layer, implementing reusable Data Access Objects, implementing conversations, and using NHibernate in an Enterprise Services application.

Conclusion

First let's start with the things that I like about the book. As far as I know it is the only book published about NHibernate, and great OR/M deserves its own book. The book is well written and structured. It covers many aspects of NHibernate, and gives you enough information to start using NHibernate in your own project. The first part of the book is great for beginners of NHibernate. The second part covers more advanced topics and people with some experience with NHibernate should also find something useful in these chapters.

Unfortunately, there are some things that I don't like about the book. It covers NHibernate 1.2, even though 2.0 was released when the book came out. I also think that the last part of the book covers to much basic stuff about Domain Driven Design and N-tier development, instead of focusing on how to utilize NHibernate. Hopefully, the authors will release a second edition that covers version 2+, and also covers more community project, like Fluent NHibernate.

Overall I give this book 3.5 of 5 stars :)

kick it on DotNetKicks.com

Shout it

Mapping a Twitter like domain with Fluent NHibernate

Sunday, 24 May 2009 10:00 by bengtbe

I'm currently learning NHibernate, and one of the best ways to learn is to blog about it :) Since I'm not a big fan of XML files, I also wanted to use Fluent NHibernate to do the mapping. As an example I will use a social messaging domain, similar to Twitter. I will also use a Top-down approach, starting with the domain model, writing the mapping, and finally creating the database schema using the SchemaExport class in NHibernate.

The domain model

Let's start with a look at the domain model:

 

The domain model mainly consists of the User entity and the Message entity and their associations:

  • The user has a list of Messages that he/she has posted.
  • The user has a list of other users that are interested in his/hers messages, called Followers.
  • The user has a list of other users whose messages he/she is interested, called Following.
  • The message has a PostedBy reference to the user who posted it.

Both entities derive from the Entity<T> base class that contains the Id property and implements Equals and GetHashCode methods.

The domain classes

Let's take a close look at the domain classes. Below is the class for the Message entity:

public class Message : Entity<Message>

{

    public virtual string Text { get; set; }

    public virtual User PostedBy { get; set; }

    public virtual DateTime CreatedAt { get; set; }

}

It contains the message text, a reference to the user who posted it, and the time it was created.

Below is the class for the User entity:

public class User : Entity<User>

{

    public User()

    {

        Name = Url = Email = "";

        Followers = new List<User>();

        Following = new List<User>();

        Messages = new List<Message>();

    }

 

    public virtual string Name { get; set; }

    public virtual string Username { get; set; }

    public virtual string Email { get; set; }

    public virtual string Url { get; set; }

    public virtual IList<User> Followers { get; private set; }

    public virtual IList<User> Following { get; private set; }

    public virtual IList<Message> Messages { get; private set; }

 

    public virtual void AddFollowing(User user)

    {

        if (Following.Contains(user)) return;

 

        Following.Add(user);

        user.Followers.Add(this);

    }

 

    public virtual void AddMessage(string messageText)

    {

        var message = new Message

                          {

                              Text = messageText,

                              PostedBy = this,

                              CreatedAt = DateTime.Now

                          };

        Messages.Add(message);

    }

}

The User class contains some properties about the user, a list of followers, a list of following users, and a list of messages. It also contains two methods:

  • AddFollowing(User user) - Adds another user to the list of users that the current user is following. Since this is a bidirectional relationship, it also adds the current user to the other user's followers.
  • AddMessage(string messageText) - Adds a new message that the user has posted. Sets the PostedBy to the current user.

Why is everything virtual?

When using NHibernate the domain model can be close to Persistence Ignorant (PI), which means that you don't have to take any special considerations when designing the domain model, like derive from a specific base class. However to support transparent lazy-loading, NHibernate needs to return a proxy that inherit from your entity and override the properties.

If you dislike marking everything with virtual you can turn of lazy-loading, but I don't recommend doing this.

Mapping with Fluent NHibernate

As mentioned, Fluent NHibernate lets you write mapping with strongly typed C# code, instead of the traditional NHibernate XML mapping files. This allows you to use tools like ReSharper to alter both the domain and mapping files when refactoring.

The mapping files must derive from ClassMap<T> and the mapping code is done inside the constructor using lambda expressions and a fluent syntax.

Let's take a look at the mapping file for the Message entity:

public class MessageClassMap : ClassMap<Message>

{

    public MessageClassMap()

    {

        Id(m => m.Id).GeneratedBy.GuidComb();

 

        Map(m => m.Text).Not.Nullable().WithLengthOf(140);

        Map(m => m.CreatedAt).Not.Nullable();

 

        References(m => m.PostedBy, "PostedBy").Not.Nullable();

    }

}

Explanation of the mapping:

  • The Id method maps the Id property as the identifier of the Message entity. It should be generated using the GuidComb algorithm.
  • The Map method maps the Text property. It also specifies that is should not be null, and that the max length is 120.
  • The Map method also maps the CreatedAt property.
  • The References method maps the PostedBy property as a many-to-one relationship between the message and user. Hence, one message belongs to a single user, but a user can have many messages. It also specifies that the column name in the database should be PostedBy.

Let's take a look at the mapping file for the User entity:

public class UserClassMap : ClassMap<User>

{

    public UserClassMap()

    {

        Id(u => u.Id);

        Map(u => u.Name).Not.Nullable().WithLengthOf(50);

        Map(u => u.Username).Not.Nullable().WithLengthOf(50).Unique();

 

        Map(u => u.Email).Not.Nullable().WithLengthOf(100);

        Map(u => u.Url).Not.Nullable().WithLengthOf(100);

 

        HasMany(u => u.Messages).LazyLoad().Cascade.All()

            .KeyColumnNames.Add("PostedBy");

 

        HasManyToMany(u => u.Following).LazyLoad()

            .WithParentKeyColumn("FollowerId")

            .WithChildKeyColumn("FollowingId");

 

        HasManyToMany(u => u.Followers).LazyLoad()

            .WithParentKeyColumn("FollowingId")

            .WithChildKeyColumn("FollowerId").Inverse();

    }

Explanation of the mapping:

  • The mapping of the Id, Name, Email, Url does not contain any new syntax.
  • The mapping of the UserName property uses the Unique method to specify uniqueness. This will create a unique constrain in the database schema.
  • The HasMany method maps the Messages property as a one-to-many between the user entity and message entity. The Cascade.All means the message will become persistent when you add it to a persistent user. The messages will also be deleted when you delete the user. It also specifies that the name of the column should be PostedBy in order to make sure that it uses the same column as specified in the message mapping. 
  • The HasManyToMany method maps the Following as a many-to-many mapping between users with specified column names.
  • The HasManyToMany method maps the Followers as a many-to-many mapping between users. This is the inverse of the Following association, hence the call to Inverse().

We also call LazyLoad() to specify that we want support for lazy loading of the lists.

Is something missing in the mapping?

You might have noticed that we often don't specify the table or column name in the mapping. In these cases the table will get the same name as the class, and the column will get the same name as the property. Below is an example of how to specify table and column names:

WithTable("TBL_MESSAGES");

Map(c => c.CreatedAt, "COL_CREATEDAT").Not.Nullable();

You also don't need to specify the type of the properties (e.g. that PostedBy is of type User). NHibernate uses reflection to determine the type.

Creating the database

In a top-down approach you change the database after you make changes to the domain or the mapping. During development you can recreate the database using the SchemaExport class in a test or console application. Below is an example using an explicit test in NUnit: 

    [TestFixture]

    public class DatabaseSetup

    {

        [Test, Explicit]

        public void SetupDatabase()

        {

            FluentConfiguration conf = NHConfiguration.CreateConfiguration(false);

            conf.ExposeConfiguration(BuildSchema)

                .BuildSessionFactory();

        }

 

        private static void BuildSchema(Configuration conf)

        {

            new SchemaExport(conf).Drop(false, true);

            new SchemaExport(conf).Create(false, true);

        }

    }

}

The test is marked with the Explicit attribute because you want to control when this test is run, e.g. you do not want to run it every time you run your tests. The SetupDatabase() test receives a FluentConfiguration from the NHibernate configuration class in the project. The database is created in the BuildSchema method that is passed to the ExposeConfiguration method. The call to BuildSessionFactory() is needed to trigger the FluentConfiguration to actually execute the call to the BuildSchema method.

Finally the database schema

Below is the database schema that has been created from the domain model and the mappings:

 

Some notes about the database schema:

  • The length of the nvarchar fields are according to the WithLengthOf call in the mappings.
  • All fields are not nullable because of the Not.Nullable() call in the mappings.
  • The many-to-many association between users are represented using the UserToUser junction table.
  • The one-to-many association between the message and users are done by the PostedBy column in the Message table.
  • It is not shown in the diagram, but Username has a unique constrain due to the Unique() call in the mappings.

Conclusion

In this post I have shown how to use Fluent NHibernate in a top-down approach in a Twitter like domain. Since I'm fairly new to NHibernate I welcome any comments and suggestions!

kick it on DotNetKicks.com   Shout it


Using AutoMapper to map view models in ASP.NET MVC

Tuesday, 14 April 2009 06:27 by bengtbe

In projects that have complex domain models it is often necessary to map the domain models to simpler objects such as Data Transfer Objects (DTO) which is "an object that carries data between processes in order to reduce the number of method calls" or Presentation Models which "represent the state and behavior of the presentation independently of the GUI controls used in the interface".

The mapping code is often boring and tedious to write, so when I first read about AutoMapper it triggered my interest. In this post I will take a first look at AutoMapper, and show how it can be used to map a complex domain model to a view model in an ASP.NET MVC application.

About AutoMapper

The project homepage describes AutoMapper as "a fluent configuration API to define an object-object mapping strategy. AutoMapper uses a convention-based matching algorithm to match up source to destination values. Currently, AutoMapper is geared towards model projection scenarios to flatten complex object models to DTOs and other simple objects, whose design is better suited for serialization, communication, messaging, or simply an anti-corruption layer between the domain and application layer."

AutoMapper is a fairly new project; the current version is 0.30 Beta, and it seems to be in active development.

A complex domain model

The domain model that I'm going to use in this example is a Customer class that has a reference to an Address class: 

public class Customer

{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Email { get; set; }

    public Address HomeAddress { get; set; }

 

    public string GetFullName()

    {

        return string.Format("{0} {1}", FirstName, LastName);

    }

}

The Address class is as follows: 

public class Address

{

    public string Address1 { get; set; }

    public string Address2 { get; set; }

    public string City { get; set; }

    public string PostalCode { get; set; }

    public string Country { get; set; }

}

Ok, I admit that this domain model is not very complex, but it will serve the purpose of this post :)

The simple view model

The view is going to show a list of customers with name, email and country. We therefore create a view model called CustomerListViewModel:

public class CustomerListViewModel

{

    public string FullName { get; set; }

    public string Email { get; set; }

    public string HomeAddressCountry { get; set; }

}

I save this view model in the file ViewModel/Customers/CustomerListViewModel.cs in the web-project. In an ASP.NET MVC application the view models belong to the Web-project, they are not part of the domain model. Usually a view model belongs to a single controller, and its views.

The controller

The URL used to display the customers should be http://application/Customers/, hence the name of the controller is CustomersController, and the action used is the Index():

public class CustomersController : Controller

{

    private readonly ICustomerService m_CustomerService;

 

    public CustomersController(ICustomerService customerService)

    {

        m_CustomerService = customerService;

    }

 

    // GET: /Customers/

    public ActionResult Index()

    {

        IList<Customer> customers = m_CustomerService.GetCustomers();

 

        Mapper.CreateMap<Customer, CustomerListViewModel>();

        IList<CustomerListViewModel> viewModelList =

           Mapper.Map<IList<Customer>, IList<CustomerListViewModel>>(customers);

 

        return View(viewModelList);

    }

}

In the above controller I use Dependency Injection to inject the CustomerService in the constructor. In a previous post I have shown how to use Dependency Injection in the controllers.

When using AutoMapper you first have to create a map between the two classes:

Mapper.CreateMap<Customer, CustomerListViewModel>();

The following line maps the list of Customers to a list of CustomerListViewModel:

IList<CustomerListViewModel> viewModelList =

   Mapper.Map<IList<Customer>, IList<CustomerListViewModel>>(customers);

If you just wanted to map a single instance you would use: 

CustomerListViewModel viewModel = Mapper.Map<Customer, CustomerListViewModel>(customer);

AutoMapper will perform the following mapping automatically:

  • FullName gets its value by calling the Customer.GetFullName() method.
  • Email gets its value from the Customer.Email propery.
  • HomeAddressCountry gets its value from the Customer.HomeAddress.Country property.

The view

Below is the view used to display the view model: 

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"

       Inherits="System.Web.Mvc.ViewPage<IEnumerable<CustomerListViewModel>>" %>

<%@ Import Namespace="MyApp.Web.ViewModels.Customers"%>

 

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

 

    <h2>Customer list</h2>

 

    <table>

        <tr>

            <th>Name</th>

            <th>Email</th>

            <th>Country</th>

        </tr>

    <% foreach (var customer in Model) { %>

        <tr>

            <td><%= Html.Encode(customer.FullName) %></td>

            <td><%= Html.Encode(customer.Email) %></td>

            <td><%= Html.Encode(customer.HomeAddressCountry) %></td>

        </tr>

    <% } %>

    </table>

</asp:Content>

 

<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server"></asp:Content>

As you can see from the Inherits attribute, this view is strongly typed to the IEnuerable<CustomerListViewModel>. The foreach uses the Model property to retrieve the list of CustomerListViewModel, and creates a table row for each instance.

Some advanced features of AutoMapper

In the example above I have shown some simple usages of AutoMapper. I will now take a quick look at some of its more advanced features:

Let's say that the Customer has a Birthday property of type DateTime that we want to map to a YearOfBirth property of type int

Mapper.CreateMap<Customer, CustomerListViewModel>()

    .ForMember(dest => dest.YearOfBirth, opt => opt.MapFrom(src => src.Birthday.Year));

Don't get confused by all the lamdas (=>). The ForMember method just says YearOfBirth should get its value from Birthday.Year.

AutoMapper can also help you test the mapping: 

[Test]

public void Should_be_able_to_map_Customer_to_CustomerListViewModel()

{

    Mapper.CreateMap<Customer, CustomerListViewModel>()

        .ForMember(dest => dest.ThisIsMappedElsewhere, opt => opt.Ignore());

    Mapper.AssertConfigurationIsValid();

}

In the above test AutoMapper will check to make sure that every single member on CustomerListViewModel has a corresponding member on the Customer, except for the property ThisIsMappedElsewhere that we told it to ignore.

There are many more features that I haven't covered. You can find more information in the following places:

kick it on DotNetKicks.com   Shout it

Book review: Microsoft .NET: Architecting Applications for the Enterprise

Monday, 9 March 2009 08:17 by bengtbe

Authors: Dino Esposito & Andrea Saltarello
Publisher: Microsoft Press
Purchase: Amazon.com, Amazon.co.uk

Introduction

I first heard of this book when Jeremy Miller (the maker of StructureMap) wrote that he was impressed by it. So I decided to purchase it, and now I have finished reading it. Before I give my conclusion, lets start with a summary of the different chapters in the book.

1. Architects and Architecture Today

Discusses the design of architecture and the role of the architect. Also gives a brief overview of different models for software development: Waterfall, Agile and Microsoft Solutions Framework.

2. UML Essentials

Covers the most important UML diagram types - Use Case, Class, and Sequence Diagrams. Describes three main modes of using UML - Sketch mode (emerging design), Blueprint mode (up front design), and Programming mode (Model-Driven Architecture).  The authors prefer to use UML as a sketching tool to communicate ideas, which seems like a sensible choice.

3. Design Principles and Patterns

Looks at goals of design principles and design - High Cohesion, Low Couping, and Separation of Concerns. Also looks at more advanced Object-Oriented Design principles - Open/Closed Principle, Liskov's Substitution Principle, and Dependency Inversion Principle. Aspect-Oriented programming (AOP) is also explained by looking at Microsft's Policy Injection Application Block.

This concludes the first part of the book, the rest of it looks at how to design a system by going through each application layer.

4. The Business Layer

Discusses different ways to organize business logic. The business logic can either be organized around user actions or around the domain. When organizing the logic around user actions, either the Transaction Script (TS) or Table Module (TM) pattern can be applied. These are best suited for low complexity in the domain. When organizing around the domain a Domain Model (DM) pattern can be applied. This pattern can deal with high complexity in the domain.

5. The Service Layer

The service layer is placed between the presentation layer and the business layer, it can also be thought as the upper part of the business layer. It basically is a list of actions that can be triggered from the user interface. One of its main responsibilities is dealing with roles and security. The chapter also discusses the following patterns that are related to the service layer - the Remote Facade Pattern, the Data Transfer Object Pattern, and the Adapter Pattern. It has a good discussion on when to use DTO's and when it can be considered overkill. It gives a brief introduction to Service-Oriented Arhcitecture (SOA). Finally, it discusses the Serivice Layer in regards to AJAX.

6. The Data Access Layer

Starts off with a discussion of the responsibilities of a Data Access Layer (DAL), and how it "communicates" with the other layers. Then it describes patterns and principles to use when manually designing your own DAL - Service Locator, Inversion of Control, Transactions, Data Context, Query by Criteria, Unit of Work, Concurrency, and Lazy Loading. Afterwards it looks how an Object/Relational Mapper (OR/M) tool can be used to power the DAL, using NHibernate as an example. The authors consider NHibernate to be the de facto standard for O/RM tools, while Entity Framework (EF) is not yet mature enough. At the end of the chapter there is a great section called "To SP or Not to SP", where the authors dispel many myths about Stored Procedures. At last, a book from Microsoft where SP are not described as the core of a DAL :)

7. The Presentation Layer

Presents the responsibilities of the presentation layer, and splits it into two segments - the user interface and presentation logic. Gives a great overview of the evolution of presentation patterns - Autonomous Views (AV), Model-View-Controller (MVC), Model2, Model-View-Presenter (MVP), and Presentation Model (PM). Also shows examples from different presentation frameworks - Web Client Software Factory, ASP.NET MVC Framework, MVC# Framework, and Windows Presentation Foundation.

Conclusion

I truly recommend this book to both intermediate and senior .NET developers. It has a great coverage of many current thoughts and aspects of system architecture. Many of the patterns in the book are from Patterns of Enterprise Application Architecture by Martin Fowler, and the book sets them into perspective in an enterprise .NET application. I like that a Microsoft Press book describes and even recommends Open Source tools, e.g. the book recommends NHibernate over Entity Framework. Dino's writing is very consise and clear, and the book is full of code-examples, not just theory. However, since the scope of the book is very big, it cannot go into too much detail. So don't expect to learn all you need about e.g. Domain Driven Design or NHibernate by reading this book.

Overall I give this book 4.5 of 5 stars :)

kick it on DotNetKicks.com

Shout it