100% found this document useful (2 votes)
2K views

Building N-Layered Applications With ASP - NET 4.5 PDF

Imar spaanjaars: Thanks for buying my article series "building n-layered applications with ASP.NET 4.5" if you run into problems with the article or the code presented in it, you have a few different options. If you have any questions or feedback (good or bad), use the contact options I described above.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
2K views

Building N-Layered Applications With ASP - NET 4.5 PDF

Imar spaanjaars: Thanks for buying my article series "building n-layered applications with ASP.NET 4.5" if you run into problems with the article or the code presented in it, you have a few different options. If you have any questions or feedback (good or bad), use the contact options I described above.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 164

Building N-Layered Applications

with ASP.NET 4.5








2013 - Imar Spaanjaars http://imar.spaanjaars.com

Dear reader,
Thank you for buying my article series Building N-Layered Applications with ASP.NET 4.5.
Thanks to your support I can continue to run http://imar.spaanjaars.com and add fresh
content as often as possible.
If you run into problems with the article or the code presented in it, you have a few
different options:
1. First, try posting your question at the end of one of the articles on my site that deals
with your question using the Talk Back feature at the bottom of the page. This is the
best solution as others will be able to join and learn from the discussion as well. You
find the full article series here: http://imar.spaanjaars.com/573/aspnet-n-layered-
applications-introduction-part-1.

2. If you have a question you dont want to share with the community, use the Contact
page on my website at: http://imar.spaanjaars.com/contact. Before you post there,
please consider whether your question isnt much better off posted at the end of
one of the articles. This makes it easier for me to answer it only once, and refer
others to the answer if they have the same question.

3. Finally, you can send an e-mail to [email protected]. I typically try to answer e-
mail within 2 or 3 business days, but please allow for a longer time in some cases.
I hope youll enjoy reading this series as much as I enjoyed writing it. If you have any
questions or feedback (good or bad), use the contact options I described above. I love to
hear what you think of this series.
If you havent bought this series, but got it from a friend, a colleague or elsewhere, please
consider buying the series through my website at http://imar.spaanjaars.com/587/new-
article-series-on-aspnet-45-n-layered-design-now-available-for-purchase. Its not expensive,
and by buying the series, you help me to keep run http://imar.spaanjaars.com.
Have fun and happy N-Layering!

Imar Spaanjaars
ASP.NET N-Layered Applications - Introduction (Part 1)
Now that the RTM versions of Visual Studio 2012 and .NET 4.5 have been out for a while, it seems like a good time to
finally write the follow up to my popular series on N-Layered design using ASP.NET 3.5
(1)
that I wrote in 2008 and
early 2009. I have been wanting to do this for a long time, but there were always other things on my Todo list with a
higher priority. The wait has been worth it though; since the last series targeting .NET 3.5 that I published in late 2008
and early 2009, new and compelling technologies have been released that make writing an N-Layered application such
as the Contact Manager a lot easier to write.
Introduction
In this new article series you'll see how to design and build an N-Layered ASP.NET application using ASP.NET MVC 4,
ASP.NET 4.5 Web Forms and a number of other up-to-date technologies such as Entity Framework 5 and WCF. In this
series, I'll build a sample application to manage contact people called the ContactManager v4.5 application, similar to
the demo application demonstrated in the previous article series. Over the next 10 articles I'll dissect the sample
application (that you can download at the end of each article, starting with Part 2) and show you how I designed and
built it.
Although you find full details in the remainder of this series, heres a quick list of all the technologies and concepts Ill
be using for the ContactManager application.
Entity Framework (EF) 5 with Code First for all data access.
MVC 4, Web Forms 4.5, WCF and a command line tool for four different frontend implementations.
Unit and integration tests to make the model and application testable.
NuGet
(2)
to quickly bring in additional libraries and assemblies.
FluentAssertions
(3)
to make unit tests more straightforward to write and easier to read, especially for
non-technical people.
A Dependency Injection (DI) framework called StructureMap
(4)
to make it easier to program against
interfaces and determine the concrete types at run time as well as improve the testability of your code.
A framework called AutoMapper
(5)
to automatically map between your own domain objects and View Models
in MVC and other applications.
DynamicQuery
(6)
, a helper library from Microsoft to write string based LINQ expressions for sorting and
filtering data.
FileHelpers
(7)
, a third-party library to read CSV files which Ill use in Part 9 to import data from a text file
through the applications API into the database.
NLog
(8)
, a logging framework for .NET.
Why an N-Layered Architecture?
Using an N-Layered architecture for your ASP.NET applications brings a number of benefits, such as:
Separation of concerns - by putting code in separate layers, you separate the various parts of your
application, such as data access, business logic and the UI. This makes it easier to design and build the
application and makes it possible for developers in multiple
disciplines (database, server side programming, frontend development, design) to work on the application in
parallel.
Abstraction - With a layered architecture it's easier to look at a complete application and understand the roles
and responsibilities of individual layers and the relationship between them. Each layer has its own
responsibilities which allows you to analyze them in isolation.
Testability - with a layered architecture, it's much easier to test each layer separately with unit tests as there
are fewer dependencies between the various layers. This means, for example, that you can test your business
logic or your UI without requiring a real database to test against.
Replaceability - It'll be easier to swap out layers. For example, you can replace your data access technology
without affecting the other layers higher up in the stack.
Reuse - You can reuse one or more layers in different applications. You'll see the benefits of this in part 6
through 9 where the same data access and business layers are reused in four different frontend application
without requiring any changes to the lower layers.
Note that there is a big difference between N-Layers and N-Tiers. N-Layers deal with separate software layers and
helps you group code logically within the application. N-Tiers on the other hand deals with the physical location of your
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 1 of 162
software components: e.g. the machines where your code runs. This article series deals with N-Layer exclusively,
although you could reuse much of it in an N-Tier application as well.
Introducing the Contact Manager Application
In this article series Ill use the same sample application that I used in the previous article series: a simple contact
manager application that enables you to manage your contacts and their contact data such as phone numbers and
e-mail addresses. But rather than a single Web Forms demo application, the new sample solution has four different
frontend applications: an ASP.NET MVC 4 web site, a Web Forms site, a WCF service project and a Command Line
application.
When you start up one of the two web applications (the MVC or the Web Forms version) you see the home screen with
a short welcome text. The People menu shows a list with all the contact people in the system with links to edit and
delete them, and to manage their contact data:
(9) See Links in this Document at the end for the full URL of this image.
Figure 1-1 The MVC site showing all contact people
When you click Edit you see the following page:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 2 of 162
(10) See Links in this Document at the end for the full URL of this image.
Figure 1-2 Editing a contact person in the MVC site
By clicking one of the address links for a contact person in the list with people (visible in Figure 1-1), you see a screen
that lets you manage address details. Figure 1-3 shows the Web Forms version of the Edit address screen. The user
has already pressed Save and the validation (from the Address class in the Model project) has kicked in:
(11) See Links in this Document at the end for the full URL of this image.
Figure 1-3 Editing an Address in the Web Forms application
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 3 of 162
When you click the Email addresses or Phone numbers link in the list of contact people, you see a list of associated
contact details for that person:
(12) See Links in this Document at the end for the full URL of this image.
Figure 1-4 Managing contact data in the Web Forms application
From here, you can manage the existing data (edit and delete) as well as create new e-mail addresses for this contact.
The WCF project lets you execute CRUD (Create, Read, Update and Delete) methods against the contact people in the
database over the network which is useful for machine-to-machine interactions.
Finally, the Command Line tool shows how to import data from a source like a CSV file to get existing data into the
database through the applications API.
As you can see, the functionality is rather simple which makes it easier to focus on the core concepts. However, when
designing and building the sample application I havent taken any shortcuts or oversimplified things. Anything you see
in the sample solution can be used to build real-world, large scale web applications.
History of the Contact Manager Application
This is the third version of the Contact Manager Application used to demonstrate N-Layer design concepts in ASP.NET.
The first version was released in January 2007 and came as a single Web Site Project with all the UI, data access and
business logic in a single project. The second version was released in November 2008. It introduced a Web Site Project
for the UI as well as a number of class library projects for the business logic layer, the entities, the data access layer
and the validation.
The previous design brought a lot of advantages in terms of separation of concerns and code that was relatively easy
to understand and maintain. However, it did have a number of drawbacks that made it more difficult to use as Ive
learned in the past few years while building real-world web sites and applications based on this design. Ill discuss
these drawbacks in the next section. The solution to these drawbacks are discussed in the remainder of this article
series.
Room for Improvement
Heres a list of some of the issues that I ran into when building applications based on the previous design:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 4 of 162
The solution required quite a lot of code in each of the layers. You needed code in the dumb data object, you
needed a Manager class in the Business layer for validation of business rules, you needed a Manager class in
the Data layer for database access and you needed quite a lot of code in stored procedures. Probably the
biggest downside of this code is that most of it is repetitive, forcing you to write the same code over and over
again for each of your implemented main entities.
Because of the tight coupling with the database layer, it was a challenge to test both the DAL and the code that
uses the database layer, especially when used in other applications such as an ASP.NET MVC web site.
The solution required a lot of stored procedures, making maintenance and testing hard. For simple CRUD
operations you needed at least four stored procedures (GetItem, GetList, InsertUpdateItem and
DeleteItem) while you needed even more code to implement advanced scenarios such as filtering and sorting.
Adding members to the data entities was pretty difficult. Besides adding the member to a class in the
BusinessEntities project, you also needed to add support for it in the various Manager classes and stored
procedures. This meant lots of updates in lots of different places for something as simple as adding a new
property.
The solution contained a lot of code to interact with the database. With the may ORM (Object Relational
Mapping) systems available today, you really shouldn't have to write your own data access code anymore. For
more information, check out: http://lostechies.com/jimmybogard/2012/07/24/dont-write-your-own-orm/.
The framework used its own validation mechanism. While this has served me (and others) well over the years,
better alternatives are now available that make it easier to implement validation in your business entities. In
addition, frameworks like ASP.NET MVC and Entity Framework (EF) have built-in support for this newer
validation mechanism.
The application used an anemic design model
(13)
, where business logic is implemented in separate classes
that modify the state of your model objects. This is now considered an anti-pattern.
A Look Ahead
Youll see how I am addressing these concerns in the new version of the application over the next 10 articles. To give
you an idea of what to expect in this series, heres a short summary of each of the 10 articles:
Part 1 - Introduction
In this article (which is what youre reading right now), youll get a high-level overview of the architecture and see how
I set up my projects, namespaces, classes etc. Ill describe the purpose and responsibility of each of the main projects
and how they work together.
Part 2 - Setting up the Solution in Visual Studio
In this article Ill show you how to setup the solution using Microsoft Visual Studio 2012. Ill show you how to organize
your projects and solution on disk, and how to prepare the solution for integration with TFS so it allows for easy team
development and branching. Ill show you how to use NuGet to add and maintain third party libraries in the projects.
Part 3 - Making your Project Unit Testable
This article shows you how to add unit test projects to your solution and how to set them up. Ill be using a third party
library called FluentAssertions to make your tests easier to write and understand.
Part 4 - Implementing a Model
In this article youll see how to set up the domain model for the application. It borrows heavily from the original
application by reusing the main classes from the BusinessEntities project. This part focuses purely on the domain
model, as interaction with the database is handled by a separate Visual Studio project that uses EF Code First,
discussed in Part 5.
Part 5 - Implementing a Repository with Entity Framework 5 Code First
In this article youll see how to use Entity Framework 5 Code First to implement a data access layer that maps your
model to an underlying (SQL Server) database. Ill show you how to use the repository pattern to centralize data
access code and make it available to other calling code. This article also talks about validation. Validation was a big
feature of the 3.5 version of my framework, so it makes sense to implement it in the new version as well. Youll see
how to implement a validation strategy that is somewhat similar to the previous design in that it provides both
property and object level validation. However, using built-in functionalities from the .NET Framework and the Entity
Framework will make it much easier to implement the same validation in other applications such as an ASP.NET MVC
site.
Part 6 - Putting it all together - Implementing an MVC 4 Frontend
In this article youll see how to implement an MVC 4 frontend using the model and repositories introduced in the
earlier articles. The demo application enables you to manage contact people as well as their contact details such as
addresses, e-mail addresses and phone numbers. Youll see how to use Dependency Injection to inject the repository
and other dependencies into the MVC controllers and how the controllers then use the repository to get data in and out
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 5 of 162
of the database.
Part 7 - Putting it all together - Implementing a Web Forms 4.5 Frontend
In this article youll see how to implement an ASP.NET 4.5 Web Forms frontend using the model and repositories
introduced in the earlier articles. The frontend of the application is almost the same as the MVC application, but now
everything is implemented using ASP.NET 4.5 Web Forms and the new model binding capabilities introduced in
ASP.NET 4.5.
Part 8 - Putting it all together - Implementing a WCF 4.5 Frontend
In this article youll see how to implement a WCF 4.5 service frontend using the model and repositories introduced in
the earlier articles. The WCF service enables calling applications to retrieve contact people. In addition it also allows a
calling application to create new and modify and/or delete existing contact people.
Part 9 - Import Tool - Importing Data from the old Database using the API
This article shows you how to use the API of the application to import legacy data from an existing data source such as
a CSV file. This serves as an example on accessing data using an application that has no UI and that just uses the
applications API.
Part 10 Extensions, Tools and Wrapping Up
In the final part of the series Ill show you some interesting tools that you can use when building applications like the
ContactManager. Ill also look at some extensions you could write and then summarize the full series.
Note: Part 2 and 3 of the series contain a lot of hands-on, step by step instructions as these articles show you how to
setup a solution like the Spaanjaars.ContactManager application yourself. You can use these instructions pretty much
as-is for your own applications. The remaining parts in the series then analyze the working code for the
Spaanjaars.ContactManager application that you can download at the end of each article. Ill show a lot of the code in
detail, and explain how it works, but you wont find detailed step by step instructions on how to add the code and files
to the various projects.
Overview of the Architecture
In this section Ill give you an overview of the complete application. Youll see the main architecture, how I set up the
various Visual Studio projects and how I linked them together. In addition youll see many of the important classes and
other types inside each of the projects and learn about their responsibilities.
From a high level point of view, the architecture of the Spaanjaars.ContactManagerV45 solution looks as follows:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 6 of 162
(14) See Links in this Document at the end for the full URL of this image.
Figure 1-5 The Architecture of the Spaanjaars.ContactManagerV45 Application
The blue boxes at the bottom represent the data access layer, the green box in the middle represents the business
layer and the orange boxes at the top represent the UI. The business layer also contains the model with all the main
entities but thats not shown in this diagram yet. Youll see more of the model in Part 4.
At the bottom, you see a SQL Server database which is, just as in the previous series, the relational database used for
the application. Above the database you can see the Entity Framework DbContext; the main class used for Entity
Framework 5 Code First which is what Ill use in this article series. Above this you can see a layer containing concrete
repositories which use the Entity Framework DbContext internally. Note that this is just an implementation decision.
The concrete repositories implement the interfaces defined in the green Repository Interfaces layer which means you
can swap the concrete repositories and the Entity Framework for alternatives; for example you could build a concrete
repository that uses NHibernate or Teleriks OpenAccess ORM. The user interface applications that you see at the top of
the diagram would never know you swapped the underlying data access technology as all they are aware of are the
interfaces in the business layer. The exception to this is the command line application tool that youll see in Part 9 of
this series. Since this application can be considered a one-off or throw away application, I havent bothered trying to
decouple it from the concrete repositories that use EF.
Youll see much more of this in the remainder of this series as I dig deeper into the various layers and explain how
they are constructed.
From a Visual Studio perspective, the application looks as follows:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 7 of 162
Figure 1-6 The Solution Explorer showing the Spaanjaars.ContactManagerV45 Application
Notice how I used Visual Studio Solution Folders
(15)
to group related project types (such as Tests and Frontend (UI)
projects). This makes it easier to understand how the solution is organized and it helps you to quickly show or hide a
particular group of projects youre working with.
At the bottom of the Solution Explorer you can see three projects. The Spaanjaars.Infrastructure project contains a
number of plumbing classes and interfaces used throughout the solution. The Spaanjaars.ContactManager45.Model
project contains the core domain classes such as Person and Address and is somewhat similar to the
BusinessEntities project from the 3.5 version of my N-Layer design. The Repositories.EF project contains all the
code to interact with a SQL Server database using Entity Framework (EF) 5 Code First. Note that for the project names
I use the pattern: Company.Project.Layer where Company is your companys or your clients name, Project is the
name of the application and Layer specifies the type of project in the stack. You see more of this at the beginning of
Part 2.
The Frontend folder contains four UI or frontend projects: one using ASP.NET MVC 4, one using ASP.NET Web Forms
4.5, one using WCF and a Command Line tool used for import of data. Youll see these projects in later articles in this
series. Under the hood, these projects make use of the various Model and Repositories projects.
The Tests Solution Folder contains a number of test projects for unit, integration and UI / MVC / WCF tests. These
projects are discussed in Part 3.
This may look a little overwhelming, leading you to wonder why you need so many projects for a relatively simple
application. If thats the case, its important to realize you typically dont need that many projects. In my sample
application I have four different frontends, demonstrating N-Layer design in various types of applications. Also, for
these projects I have separate test projects, quickly increasing the total number of projects. For my new design, the
minimum number of projects you need is four: the three projects in the root of the solution explorer and at least one
frontend application that uses these three projects.
To see how these projects relate to each other, consider the following model diagram that shows the dependencies of
the two Web frontend and the WCF projects:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 8 of 162
(16) See Links in this Document at the end for the full URL of this image.
Figure 1-7 A model diagram showing various components of the Application
This figure shows how the Model project references the Infrastructure project, and nothing else (except for the .NET
framework libraries of course which are not shown in this diagram.) The Repositories.EF project using Entity
Framework (EF) references the Model project as well the Infrastructure project. The three Frontend projects (MVC,
Web Forms and WCF) have a reference to the Model and Infrastructure projects as well as a reference to the
Repositories.EF project. This latter reference isnt strictly needed as all the code in the UI projects is based on
interfaces defined in the Model project. Using a Dependency Injection framework such as Ninject or StructureMap you
could inject the concrete types in the EF project at run-time, without any compile-time dependency on this project.
However, I prefer to write the bootstrapper code (code that configures the Dependency Injection framework, discussed
in detail in Part 6 and 8) in my project over configuration files, and so the UI projects each have a reference to the EF
project. If I wanted to switch to a repository that uses another ORM such as NHibernate or other data access
technology such as ADO.NET, all I would need to do is replace the project reference and rewrite the bootstrapper code.
Youll see more of this in part 5 when the EF Repository is implemented.
Although the details of the individual projects are discussed in great detail in the remainder of this article series, heres
an overview of how all the different projects work together:
The Model project defines all the core entities and their validation rules. Here you find classes such as Person
and EmailAddress. You also find an IPeopleRepository which is an interface that defines the contract for
working with Person objects. The types in the Model project are used by the UI projects. For example, the MVC
project uses Person to display information about people in the system, as well as accept modifications to those
objects (Insert, Update and Delete). These types are not directly used by the UI (such as Views) but are
converted to View Models as youll see later in the series.
The UI projects dont directly access the database to get their data. Instead, they use repositories that in turn
access the database. A repository makes it easier to centralize data access code and make it available to other
calling code. In my application, the Model project defines the contract for the repository which is then
implemented in the Repositories.EF project. This project uses Entity Framework under the hood to get data
in and out of the database.
The MVC and other UI projects use a concrete PeopleRepository from the Repositories.EF project. However,
they dont have a hardcoded link to this class as that would make it both difficult to replace EF with another
database technology and unit test your UI applications. Instead, the UI projects work with the
IPeopleRepository interface, while a concrete EF implementation is supplied at run-time using a concept
called Dependency Injection.
The Spaanjaars.Infrastructure project provides low-level plumbing services used by all the other projects.
The various test projects have references to other parts of the application they are testing. For example, the
integration tests project has a reference to the Repositories.EF project as it accesses a real database during
its tests.
The application makes use of the Repository pattern. For alternatives to this pattern, see:
http://lostechies.com/jimmybogard/2012/09/20/limiting-your-abstractions/
http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/
Ill discuss each of the projects in the Solution Explorer next. Youll find a high-level overview here with pointers to
other articles in the series for more in-depth information.
Spaanjaars.Infrastructure
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 9 of 162
This is a fairly simple project with only a few classes, shown in Figure 1-8:
Figure 1-8 The Solution Explorer for the Spaanjaars.Infrastructure Project
As you can tell from its name, this project isnt directly tied to the ContactManager application, Instead, I placed it in
the more general Spaanjaars.Infrastructure namespace (which could be your company name or other root level
namespace you might use) so it can easily be reused across multiple projects. This project provides three plumbing
interfaces that the rest of the application uses. Figure 1-9 shows the class diagram for this project:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 10 of 162
(17) See Links in this Document at the end for the full URL of this image.
Figure 1-9 The Class Diagram of the Spaanjaars.Infrastructure Project
The IRepository interface defines the contract that concrete repositories need to implement. It defines the members
you interact with to get data in and out of the underlying data source. Youll see an implementation of this interface
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 11 of 162
along with the unit of work related interfaces in Part 5 when you see how to build a concrete repository using Entity
Framework. Its easy to build your own repository that targets a different database or ORM. All it needs to do is
implement this interface and then you can plug it into another application such as a public facing ASP.NET MVC
website.
DomainObject<T> and ValueObject<T> are the base classes for the various domain classes in the Model project.
DomainObject<T> is the base class for entities that have an identity and is used by classes such as Person.
ValueObject<T> is used by pure value objects that dont have their own identity. In the sample application, Address
has been implemented as a ValueObject<T> to demonstrate the differences. Youll see more of this in Part 3.
Finally, in Part 5 youll see what the types in the DataContextStorage folder are used for and learn about the lifetime
of an Entity Framework object context.
Spaanjaars.ContactManager45.Model
The Model project is somewhat similar to the BusinessEntities project in the .NET 3.5 version of this application. It
features the applications core types such as Person, Address and PhoneNumber. It also features a number of
collections as well as a few enumerations to define types of contact records and people, respectively. Heres what the
Solution Explorer for the project looks like:
Figure 1-10 The Solution Explorer for the Spaanjaars.ContactManager45.Model Project
Notice the four core types: Address, EmailAddress, Person, and PhoneNumber. If youve read the previous article
series, these should all look familiar (except that Person was previously called ContactPerson). For the sake of
demonstration, I let Address inherit from ValueObject<T> which means its considered a value type while all other
classes inherit from DomainObject<T>. These last three types also have a collection counterpart that inherits from the
custom, generic CollectionBase<T> type.
The IPeopleRepository interface provides a contract that the other applications in the project work against. Youll see
a lot more of this in Part 4 and 5 of this article series.
Figure 1-11 shows the complete Class Diagram for the Model project. In later articles in this series Ill dig deeper into
the various types and their members.
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 12 of 162
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 13 of 162
Figure 1-11 The Class Diagram of the Spaanjaars.ContactManager45.Model Project
You see more of the repositories in the next section, while a detailed explanation of the EF implementation can be
found in Part 5 of this article series.
Spaanjaars.ContactManager45.Repositories.EF
This project contains all the implementation for working with contact people in a SQL Server database using Entity
Framework 5 Code First. Figure 1-12 shows the Solution Explorer for this project.
Figure 1-12 The Solution Explorer for the Spaanjaars.ContactManager45.Repositories.EF Project
This project contains concrete implementations of the repository and unit of work related interfaces you saw earlier. In
addition, it contains a number of classes related to setting up the Entity Framework, and initializing and configuring
the database using the fluent API and database creating strategy classes. You see how all of this works when setting
up Entity Framework in Part 5. For now, heres the complete class diagram:
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 14 of 162
(18) See Links in this Document at the end for the full URL of this image.
Figure 1-13 The Class Diagram for the Spaanjaars.ContactManager45.Repositories.EF project
Spaanjaars.ContactManager45.Web.Mvc
This project contains the ASP.NET MVC 4 implementation of the frontend to work with contact people and their
associated contact data in a web application. Its discussed in detail in Part 6 of this article series. Here youll see
Dependency Injection at work when the concrete repositories for the Entity Framework (or any other type you build)
are injected into the application at run-time.
Spaanjaars.ContactManager45.Web.WebForms
This project contains the Web Forms implementation of the frontend to work with contact people and their associated
contact data in a web application. Its discussed in detail in Part 7 of this article series.
Spaanjaars.ContactManager45.Web.Wcf
This project contains a WCF service to work with contact people in your system over remote services. The WCF service
has methods to retrieve, add, update and delete people from the system. The WCF project is discussed in detail in Part
8 of this article series.
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 15 of 162
Spaanjaars.ContactManager45.Import
This project contains a command line tool that can import contact people and their contact data from a CSV file. The
purpose of this project is to demonstrate how to use the applications public API from other applications. Part 9 of this
series shows how I built the import tool.
In addition to the core libraries and the four frontend projects, the solution contains four test projects, nicely grouped
together under a Solution folder called Tests. You will see how to set up the test projects in Part 3. Tests are then
added to these projects in the remainder of the articles.
Spaanjaars.ContactManager45.Tests.Unit
This project contains unit tests for the solution. Youll find some basic tests for the entities and their members, tests
for validation, and more. Part 3 of this series digs deeper into this project.
Spaanjaars.ContactManager45.Tests.Integration
Since this application relies heavily on a database, it makes sense to have a number of integration tests that make use
of the database. This way, you can test the interaction of the various components, as well as some database specific
logic such as unique constraints. Once again Part 3 of this series digs deeper into this project.
Spaanjaars.ContactManager45.Tests.Frontend.Mvc
In this project youll find a number of tests for the ASP.NET MVC frontend. While the purpose of this article is not to
show you how to write unit tests for MVC or other application frameworks, the tests in this project serve to
demonstrate that with the framework presented in this series, unit testing is easy because of the way you can inject
concrete types using a Dependency Injection framework while your application programs against an interface. This
makes it much easier to test your controllers that have dependencies on components such as repositories.
Spaanjaars.ContactManager45.Tests.Frontend.Wcf
In this project you find a number of tests for the WCF services project. Just as with the MVC project, I am using
Dependency Injection to decouple the service methods from their dependencies such as repositories to enable unit
testing.
This article series is meant as an introduction to architecting N-Layered web applications using ASP.NET 4.5 and Entity
Framework 5 Code First. This means Ill dig as deep into these technologies as appropriate to explain the topic.
However, it also means I wont provide a lot of details about side issues. For example; I may be using an open source
framework to make unit testing easier in the sample application, but I wont dig into the details on how to retrieve and
install this framework, or how to configure it for the sample application and how to use it.
Stuff I Like to Do
At the end of each article, Ill provide a section called Stuff I Like to Do where I mention a number of asides and
provide links and guidance where appropriate. For this first article, theres nothing to add yet, other than maybe a
suggestion to read Part 1 of the original article series at http://imar.spaanjaars.com/476/n-layered-web-applications-
with-aspnet-35-part-1-general-introduction so that you have a general idea of how the application was designed
previously.
Summary
In this article, you saw a brief overview of the ContactManager v4.5 application. I described some of the applications
history, and highlighted some shortcomings of the .NET 2.0 and 3.5 versions of the application. You then saw an
overview of the new framework including the various components (Visual Studio projects) that are involved. The article
concluded with a description of each project in the solution so you can see what their responsibilities are and how they
fit together. Each of these projects is discussed in more detail in later parts of this article series.
In the next part, youll see how to setup the solution in Visual Studio. Youll see how to add the Class Library projects
and four Frontend projects (an MVC 4 site, a Web Forms application, a WCF service and a command line tool) to the
solution. Ill be using all of these projects in the remaining articles in this series.
Links in this Document
(1) http://imar.spaanjaars.com/476/n-layered-web-applications-with-aspnet-35-part-1-general-introduction
(2) http://nuget.org/
(3) http://fluentassertions.codeplex.com/
(4) http://docs.structuremap.net/
(5) http://automapper.org/
(6) http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 16 of 162
library.aspx
(7) http://filehelpers.sourceforge.net/
(8) http://nlog-project.org/
(9) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01/Figure1-01_MVC_People_list.png
(10) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01/Figure1-02_MVC_Edit_Person.png
(11) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01/Figure1-03_WebForms_Edit_Address.png
(12) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01
/Figure1-04_WebForms_EmailAddresses.png
(13) http://en.wikipedia.org/wiki/Anemic_domain_model
(14) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01/Figure1-05_Solution_Architecture.png
(15) http://msdn.microsoft.com/en-us/library/vstudio/sx2027y2%28v=vs.100%29.aspx
(16) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01/Figure1-07_DependencyGraph.png
(17) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01
/Figure1-09_Spaanjaars.Infrastructure_Classdiagram.png
(18) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part01
/Figure1-13_Spaanjaars_Repositories_EF_ClassDiagram.png
ASP.NET N-Layered Applications - Introduction (Part 1)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 17 of 162
ASP.NET N-Layered Applications - Setting up the Solution in
Visual Studio (Part 2)
This is Part 2 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. The previous article provided some history of the architecture of the Contact Manager
application and gave a broad overview of the new architecture. In this installment, things get a bit more concrete
when you see how to setup a solution in Visual Studio 2012. The VS solution is going to contain three class libraries:
one for the Infrastructure, one for the applications Model and one to hold the Entity Framework (EF) Repository
implementation. Ill also add four frontend projects (an ASP.NET MVC 4, a Web Forms project, a WCF service project,
and a windows command line application) which are discussed in detail in Part 6, 7, 8 and 9 of this series respectively.
In the next article in this series Ill extend the solution with four more projects for unit, integration, UI and service
tests.
Note: as mentioned in Part 1
(1)
, this article and the next article (Part 3
(2)
) contain a lot of hands-on, step by step
instructions that show you how to setup a solution like the Spaanjaars.ContactManager application. You can use these
instructions pretty much as-is for your own applications. The remaining parts in the series analyze the working code
for the Spaanjaars.ContactManager application. Ill show a lot of the code in detail, and explain how it works, but you
wont find detailed step by step instructions on how to add the code and files to the various projects. Instead, you're
encouraged to download the code at the end of each article to see how it works.
Naming Conventions
If youve read the previous article series, youll recognize the naming conventions I use for my projects and root
namespaces. For the main projects I use the pattern: Company.Project.Layer where Company is your companys or
your clients name, Project is the name of the application and Layer specifies the type of project in the stack. I can
further divide the layer in specific project types. This gives me names such as Spaanjaars.ContactManager45.Model
and Spaanjaars.ContactManager45.Web.Mvc.
My test projects follow the same pattern for the root name and are then further divided in the type of tests (Unit,
Integration etc.) leading to names such as Spaanjaars.ContactManager45.Tests.Unit.
Note that the Infrastructure project I introduced in the preceding article is independent of the ContactManager
application and can be reused across multiple applications. As such, its called Spaanjaars.Infrastrucure rather than
Spaanjaars.ContactManager45.Infrastrucure.
Setting up the Solution
In the following section youll find detailed instructions on setting up the solution. This is useful if you want to create
your own project from scratch. If you just want to see the sample code or run the application, you can skip all these
steps and simply open the solution that comes with this article series in Visual Studio 2012. You find a link to the
source code at the end of each article.
Note: these steps are heavily borrowing from an earlier article I wrote about setting up a project for team
development and TFS
(3)
. I decided to repeat part of the steps here and make them more specific for the
Spaanjaars.ContactManager application.
Start Visual Studio 2012 and choose File | New Project. 1.
At the top of the dialog, choose .NET Framework 4.5 from the drop-down list. 2.
In the Other Project Types category click Visual Studio Solutions and then click Blank Solution. As the name of
the Solution, enter Spaanjaars.ContactManager45 and as the Location choose C:\Projects. Note: substitute
Spaanjaars and ContactManager with your own company and project names.
3.
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 18 of 162
(4) See Links in this Document at the end for the full URL of this image.
Figure 2-1 The New Project Dialog in Visual Studio 2012
Click OK. 4.
Close Visual Studio and open the project folder (at C:\Projects\Spaanjaars.ContactManager45) in File
Explorer (Windows Explorer on Windows 7 and earlier). Create a new folder called Main and then drag all of
the Spaanjaars.ContactManager45.* files from C:\Projects\Spaanjaars.ContactManager45 into this new
Main folder. Your structure now looks like this:
5.
(5) See Links in this Document at the end for the full URL of this image.
Figure 2-2 File Explorer Showing the Solution
This Main folder is used later for Branching in TFS. This all feels a bit clumsy but I see no other way to create the
solution with this name and store it in a folder called SolutionName/Main. Fortunately, this is a one-time operation.
Open the Solution in Visual Studio by double-clicking the .sln file in the Main folder. 6.
Right-click the Solution in the Solution Explorer and choose Add | New Project. 7.
In the tree on the left choose your programming language, and then choose Class Library from the Windows 8.
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 19 of 162
category.
At the top of the dialog, make sure that .NET Framework 4.5 is selected. 9.
As the name of the project, enter Spaanjaars.ContactManager45.Model. 10.
As the location for the project enter C:\Projects\Spaanjaars.ContactManager45\Main\Applications: 11.
(6) See Links in this Document at the end for the full URL of this image.
Figure 2-3 The Add New Project Dialog for the Model Project
Notice the inclusion of the Applications folder in the path. This way you can group all projects that make up the core
application in a single folder. In the next article Ill use a folder called Tests inside the Main folder to group all Test
projects.
Click OK to add the project. 12.
On disk, your solution now has the following structure: 13.
(7) See Links in this Document at the end for the full URL of this image.
Figure 2-4 File Explorer Showing the Model Project
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 20 of 162
Back in Visual Studio, delete the default Class1.cs file as you dont need it. 14.
Repeat steps 7 through 12 and 14 two more times and add the following Class Library projects:
Spaanjaars.ContactManager45.Repositories.EF 1.
Spaanjaars.Infrastructure 2.
15.
Make sure you dont forget the \Applications part in the projects location, as VS defaults to the solutions folder
instead.
Note that the Infrastructure project is generic enough to be placed in a namespace which is outside the
ContactManager application. This makes it possible to reuse the classes defined in this project in other solutions based
on the same model. For this sample application I put the project in the Applications folder, but if youre reusing it
across multiple projects youll want to store it elsewhere such as in C:\Projects directly.
In the next section youll see how to add four frontend projects to the solution. In your own projects you dont need all
four of them; just pick the one(s) you need. If you want to follow along with this series, just add all four projects.
Right-click the Solution in the Solution Explorer and choose Add | New Solution Folder. Name the folder
Frontend.
16.
The next steps show you how to add an ASP.NET MVC 4 application to the solution. If you prefer a Web Forms
or another type of application instead, skip to step 21 or later. Right-click the new Frontend folder and choose
Add | New Project. In the tree on the left, click the Web category and then choose ASP.NET MVC 4 Web
Application.
17.
As the name of the project, enter Spaanjaars.ContactManager45.Web.Mvc. 18.
As the location for the project enter C:\Projects\Spaanjaars.ContactManager45\Main\Applications. 19.
Click OK to add the project. 20.
In the New ASP.NET MVC 4 Project dialog, choose Internet as the template. Make sure Razor is selected as the
View Engine and if necessary, clear the checkbox for creating a unit test project. The unit test projects are
added separately to the solution in the next article.
21.
Repeat steps 17 through 20, but this time add a new ASP.NET Web Forms Application and name it
Spaanjaars.ContactManager45.Web.WebForms.
22.
Repeat steps 17 through 20 again, but this time add a new WCF Service Application and name it
Spaanjaars.ContactManager45.Web.Wcf.
23.
Repeat steps 17 through 20 again, but this time add a new Console Application from the Windows category
and name it Spaanjaars.ContactManager45.Import.
24.
Tip: if you forget to store one of the projects in the Applications folder, remove the project from the Solution
Explorer (right-click the project and choose Remove). Move the project to the Applications folder using File Explorer
and then add the project to the solution again using its Add Existing Project option.
Your Solution Explorer should now look similar to Figure 2-5 25.
Figure 2-5 The Solution Explorer with all Application Projects
From the Model project, add a reference to the Infrastructure project. Next, from the Repositories.EF
project, add a reference to the Infrastructure and Model projects. Finally, from each of the four frontend
projects add a reference to the Infrastructure, Model and Repositories.EF projects.
26.
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 21 of 162
Next, right-click the Solution and choose Rebuild Solution. This compiles the application and makes sure that
everything is ready for the next steps.
27.
Optimizing the Solution
Here are a few tips to get the Visual Studio solution in a good shape:
Use NuGet to update all packages that were added by Visual Studio when you created the new projects.
Libraries like jQuery, jQuery UI and Entity Framework are updated regularly, and are likely to be outdated
when you added them to the solution. To update the packages, right-click the solution and choose Manage
NuGet Packages for Solution. Next, click Updates on the left and then update each individual package that has
updates.
1.
Consider enabling NuGet Package Restore. With this feature enabled, Visual Studio downloads missing
packages whenever you build your solution. This is useful if you work in a team and use a shared code
repository such as TFS, because packages added by one member are downloaded automatically the next time
another team member builds the solution. To enable this feature, right-click the Solution and choose Enable
NuGet Package Restore. You also need this option to build the sample application that comes with this article.
See the Readme.txt file in the download for more details.
2.
Delete unneeded .cs files and other boilerplate stuff you dont need. For example, if you havent already done
so, remove the Class1.cs files from the class library projects. In addition, remove the IService1.cs,
Service1.svc and Service1.svc.cs files from the WCF project.
3.
Adding your Solution to TFS
Now that the skeleton for the solution is ready, its a good time to add it to your source control system. If you dont
use such a system, you can skip this section (although you should seriously consider using one; you can get a free
hosted TFS solution for up to five team members at http://tfs.visualstudio.com/). The following section uses TFS as
the source control system, but similar concepts apply to other source control systems.
Using Team Explorer, connect to your TFS Server. 1.
On the Solution Explorer, right-click the Solution and choose Add Solution to Source Control. 2.
Click the appropriate TFS Project. 3.
As the name for the solution folder, enter Spaanjaars.ContactManager45/Main. The /Main part is not a typo.
In fact it's very important as itll create an additional folder in TFS which you can set up as main branch later.
4.
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 22 of 162
Figure 2-6 The Add Solution to Source Control Dialog
Click OK. 5.
Your Source Control Explorer (accessible from the Team Explorer) should now look like this: 6.
(8) See Links in this Document at the end for the full URL of this image.
Figure 2-7 The Source Control Explorer
Right-click the Main folder in the Source Control Explorer and choose Check In. 7.
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 23 of 162
As a comment, enter something like Initial Commit and click Check In. 8.
Still in the Source Control Explorer, right-click the Main folder and choose Branching and Merging | Convert to
Branch.
9.
Enter a description such as Main Branch and click Convert. 10.
Thats it. From now on, other developers can get a local copy of this solution simply by opening the .sln file
from the Main folder. When they compile the application, Visual Studio will automatically attempt to download
the missing packages (provided you enabled NuGet Package Restore as explained earlier) removing the need
to store these packages in TFS.
11.
For more information about creating a branch, check out the original article on adding solutions to TFS
(http://imar.spaanjaars.com/565/recommendations-for-setting-up-a-visual-studio-solution-for-tfs). In addition, check
out the Branching and Merging guide at http://vsarbranchingguide.codeplex.com/.
Stuff I Like to Do
Here are a few tips to keep your solution in great shape, and easy to manage:
Scan the list of installed packages for each project and remove the ones you dont need. Adding them back in
later is easy to do.
1.
From time to time, scan the Updates for the installed packages. Then for each package, consider whether you
want to upgrade or not. Some updates cause breaking changes or require you to change code first.
2.
I like to keep a document in my Solution called Readme.txt or Stuff I Learned.txt where I keep a list of
interesting blog posts, references to open source projects, sample implementations and more. To add this file,
follow these steps:
In the folder where the .sln file resides on disk (at C:\Projects\Spaanjaars.ContactManager45
\Main) create a new folder called Documentation.
1.
Inside this new folder create a new text file called Readme.txt. 2.
Switch to Visual Studio, right-click the Solution and choose Add | New Solution Folder. Name the
folder Documentation.
3.
Right-click this new folder and choose Add | Existing Item. Browse for the Readme.txt file in the
Documentation folder and click Add to add the file to the solution.
4.
If youre using TFS or another source control system, right-click the solution in the Solution Explorer
and choose Check in. This enables you to store the solution files and folders in TFS as well.
5.
3.
Summary
In this article, you saw how to set up a Visual Studio solution and a number of projects. By following the
recommendations from this article with regards to project naming and their location on disk your solution will be easy
to manage for you and anybody else in your team that may need to have access to it. By storing all your projects in
folders below the .sln file, opening the application from source control is as easy as double-clicking the .sln file in
the Source Control Explorer.
In the next article
(9)
youll see how to add various flavors of unit test projects to the solution. If youre not interested
in unit testing (yet), you can skip directly to Part 4
(10)
. However, I still encourage you to read Part 3 as it might
change your mind on whether unit testing is something for you or not.
Links in this Document
(1) http://imar.spaanjaars.com/573/building-n-layered-applications-with-aspnet-45-part-1-introduction
(2) http://imar.spaanjaars.com/575/building-n-layered-applications-with-aspnet-45-part-3-making-your-projects-
unit-testable
(3) http://imar.spaanjaars.com/565/recommendations-for-setting-up-a-visual-studio-solution-for-tfs
(4) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part02/Figure2-01_The_New_Project_Dialog.png
(5) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part02
/Figure2-02_Windows_Explorer_Showing_the_Solution.png
(6) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part02
/Figure2-03_Add_New_Project_for_Model.png
(7) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part02
/Figure2-04_Windowes_Explorer_Model_Project.png
(8) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part02
/Figure2-07_The_Source_Control_Explorer.png
(9) http://imar.spaanjaars.com/575/building-n-layered-applications-with-aspnet-45-part-3-making-your-projects-
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 24 of 162
unit-testable
(10) http://imar.spaanjaars.com/576/building-n-layered-applications-with-aspnet-45-part-4-implementing-a-model
ASP.NET N-Layered Applications - Setting up the Solution in Visual Studio (Part 2)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 25 of 162
ASP.NET N-Layered Applications - Making your Projects Unit
Testable (Part 3)
This is Part 3 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to make your solution unit testable. In addition, youll see how to
setup a project for Integration tests which work similar to unit tests but that target the database directly.
Note: as mentioned in Part 1, this article (and the previous) will contain a lot of hands-on, step by step instructions
that show you how to setup a solution like the Spaanjaars.ContactManager application. You can use these instructions
pretty much as-is for your own applications. The remaining parts in the series analyze the working code for the
Spaanjaars.ContactManager application. Ill show a lot of the code in detail, and explain how it works, but you wont
find detailed step by step instructions on how to add the code and files to the various projects.
Making Your Projects Unit Testable
To ensure a better quality of your software, its highly recommended to add unit tests to your projects. This way, you
can test your code during development, minimizing the chance of introducing issues and finding and fixing them before
they ever make it into production code. This article does not explain the need for unit testing in detail nor does it
explain how to write good unit tests. For a good introduction into unit testing, check out the following references:
The Art of Unit Testing (Roy Osherove, Manning Publications, 2009: http://www.amazon.com/Art-Unit-Testing-
Examples-Net/dp/1933988274)
http://msdn.microsoft.com/en-us/library/bb385902%28v=vs.90%29.aspx
http://msdn.microsoft.com/en-us/library/hh694602.aspx
http://geekswithblogs.net/thomasweller/archive/2011/02/21/an-introductory-presentation-about-testing-
with-mstest-visual-studio-and.aspx
This article does, however, show you how to differentiate your types of tests (using different Test Projects in Visual
Studio) and how to configure the solution so that the test projects can see the relevant assemblies in the solution. In
many previous solutions I built, I use more than one test project, described in the following table:
Type Suggested name suffix Description
Unit Tests.Unit This project contains all the unit tests that dont have a
dependency on a database or the UI. In the sample application,
it contains tests for model entity properties, model validation,
and more.
For applications with a larger model you could further separate
the unit tests into separate Visual Studio projects, each named
after the area of the application they are targeting.
Integration Tests.Integration This test project contains integration tests that have
dependencies to other components of the system, such as a
database. In the sample project you find tests that use the
Repositories.EF project to interact with a SQL Server database
directly.
For applications with a larger model you could further separate
the integration tests into separate Visual Studio projects, each
named after the area of the application they are targeting.
Frontend Tests.Frontend.Mvc This test project contains tests that target the presentation layer.
It could contain Coded UI tests and tests targeting the ASP.NET
MVC controller framework. In the sample application you only
find unit tests for MVC controllers but you could easily add more
tests to this project.
Frontend Tests.Frontend.Wcf This test project contains tests for the various service methods
inside the WCF service project.
In the next steps youll see how to add these four Test Projects to the solution. I am showing you how to add all four;
one for each frontend application added to the solution in the previous article. If, however, your solution has fewer
frontend implementations, only add the test projects for your particular frontend(s).
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 26 of 162
In order to better organize my solution, I prefer to group all my test projects in a Solution Folder called Tests. This is
not required, but it makes it easier to get access to all your test projects at once, or hide them when youre working
on the actual code for the project.
To add a Solution Folder for the tests, right-click the Solution in the Solution Explorer and choose Add | New
Solution Folder. Name the folder Tests.
1.
Right-click this new Tests folder and choose Add | New Project. Select your preferred programming language
and then, from the Test category, select Unit Test Project. Name the project
Spaanjaars.ContactManager45.Tests.Unit and change the Location for the project to C:\Projects
\Spaanjaars.ContactManager45\Main\Tests. By storing your test projects in the Tests folder you separate
them from the actual implementation projects that are stored in the Applications folder. In the Target
Framework drop-down list make sure .NET Framework 4.5 is selected.
This project is going to contain the core unit tests for the Contact Manager application.
2.
(1) See Links in this Document at the end for the full URL of this image.
Figure 3-1 The Add New Project Dialog
Click OK to add the project to the solution. 3.
Add another Unit Test Project to the Tests Solution Folder, name it
Spaanjaars.ContactManager45.Tests.Integration and make sure its saved in the folder C:\Projects
\Spaanjaars.ContactManager45\Main\Tests as well. This project will contain tests that are going to access
the database directly.
4.
Add another Unit Test Project to the Tests Solution Folder, name it
Spaanjaars.ContactManager45.Tests.Frontend.Mvc and make sure its saved in the folder C:\Projects
\Spaanjaars.ContactManager45\Main\Tests. This project will contain tests that target the ASP.NET MVC 4
project.
5.
Add another Unit Test Project to the Tests Solution Folder, name it
Spaanjaars.ContactManager45.Tests.Frontend.Wcf and make sure its saved in the folder C:\Projects
\Spaanjaars.ContactManager45\Main\Tests. This project will contain tests that target the WCF service
project.
6.
In these four new test projects, add references to the following projects in your solution: 7.
Project References
Tests.Unit
Spaanjaars.ContactManager45.Infrastructure
Spaanjaars.ContactManager45.Model
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 27 of 162
Tests.Integration
Spaanjaars.ContactManager45.Infrastructure
Spaanjaars.ContactManager45.Model
Spaanjaars.ContactManager45.Respositories.EF
Tests.Frontend.Mvc
Spaanjaars.ContactManager45.Infrastructure
Spaanjaars.ContactManager45.Model
Spaanjaars.ContactManager45.Web.Mvc
System.Web.Mvc (found in %programfiles(x86)%\Microsoft
ASP.NET\ASP.NET MVC 4\Assemblies by default)
Tests.Frontend.Wcf
Spaanjaars.ContactManager45.Infrastructure
Spaanjaars.ContactManager45.Model
Spaanjaars.ContactManager45.Web.Wcf
Your Solution Explorer should now look like this:
Figure 3-2 The Solution Explorer with the new Unit Test Projects
On disk your Solution should look like this in File Explorer:
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 28 of 162
(2) See Links in this Document at the end for the full URL of this image.
Figure 3-3 File Explorer Showing the new Unit Test Projects
Finalize the configuration of your projects. For example, you can delete the existing default Unit Test files
(called UnitTest1.cs inside each project). You can also add additional packages such as FluentAssertions
(3)
(for which youll find instructions later in this article) or references to external libraries.
6.
Finally, do a full rebuild of the entire solution to ensure everything is set up correctly and resolve any
compilation errors you may have.
7.
In the next section youll see how to add a simple test to three of the four Unit Test projects in order to ensure your
projects, including the Infrastructure, Model and Repositories.EF projects as well as the Unit Test projects itself,
have been set up correctly. In order for this to work, Ill also add a few classes to the core projects with some
temporary implementation. That code will be expanded or replaced in later articles.
In the Model project, add a new public class called Person and give it an automatically implemented property
of type int called Id. You should end up with code like this:
8.
In the project Spaanjaars.ContactManager45.Tests.Unit add a new Unit Test file called PersonTests.cs
and modify the code as follows.
9.
1
2
3
4
5
6
7
namespace Spaanjaars.ContactManager45.Model
{
public class Person
{
public int Id { get; set; }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Model;

namespace Spaanjaars.ContactManager45.Tests.Unit
{
[TestClass]
public class PersonTests
{
[TestMethod]
public void NewPersonHasEmptyId()
{
var person = new Person();
Assert.AreEqual(0, person.Id);
}
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 29 of 162
Run all the tests (theres only one at the moment) in the solution by pressing Ctrl+R, followed by an A
(Ctrl+R, A) or by choosing Tests | Run | All Tests from the main menu. Then check the Test Explorer (which
you can open using Test | Windows | Test Explorer). You should see that the test has passed:
Figure 3-4 Test Explorer Showing Success
Note: You would normally write a test that fails first, to avoid ending up with false positives. You would then
implement some code to make the test pass. In this case, the test is so simple (and not really meant to test
the functionality of the Person class, but rather the setup of the test project itself) that I decided to write a
"green test" directly.
10.
Next, add a new public class called PeopleRepository.cs to the
Spaanjaars.ContactManager45.Repositories.EF project. Dont forget to add public in front of the class or
itll default to internal. Theres no need to add any code to the class for now.
11.
In the project Spaanjaars.ContactManager45.Tests.Integration, add a new Unit Test file, call it
PeopleRepositoryTests.cs and modify the code as follows:
12.
Note: this is a pretty useless test. You should have other tests that implicitly check whether you can instantiate a new
PeopleRepository class and then work with that instance. However, for now this test is useful to make sure that the
Integration project has the correct references to the Repositories.EF project.
Press Ctrl+R, A again. Both tests should pass. 13.
In the test project Spaanjaars.ContactManager45.Tests.Frontend.Mvc add a new Unit Test file called
HomeControllerTests.cs and modify its code as follows:
14.
15
16
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Repositories.EF;

namespace Spaanjaars.ContactManager45.Tests.Integration
{
[TestClass]
public class PeopleRepositoryTests
{
[TestMethod]
public void CanInstantiatePeopleRepository()
{
var peopleRepository = new PeopleRepository();
Assert.IsNotNull(peopleRepository);
}
}
}
1
2
3
4
5
6
7
8
9
10
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Web.Mvc.Controllers;

namespace Spaanjaars.ContactManager45.Tests.Frontend.Mvc
{
[TestClass]
public class HomeControllerTests
{
[TestMethod]
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 30 of 162
Press Ctrl+R, A once more. All three tests should now pass, as shown in Figure 3-5: 15.
Figure 3-5 Test Explorer Showing Green Tests
For now, these tests are really simple and only serve to verify the setup and relationships between the various
projects. I skipped the tests for the WCF service as the current project doesnt have any code files and adding a WCF
service requires more background which Ill cover in Part 8
(4)
of this series.
Ill be adding more tests to the test projects as I progress through this article series. I wont show you the code for all
of the tests though; Ill only highlight some of the more important ones. Youre encouraged to check out the source
code that comes with this article series to see all the tests.
Using Fluent Assertions
There are a number of open source frameworks available that make unit tests easier to read and more obvious. One of
those frameworks is FluentAssertions
(5)
created by Dennis Doomen
(6)
. This framework allows you write the
assertions for your test in a fluent way. E.g. rather than writing something like this:
You can now write something like this:
Although you may need to get used to this new syntax at first, I generally find it more intuitive to read. Its very useful
to quickly see what your tests do but more importantly, non-technical people involved in a project can now more or
less read unit tests too. This enables them to help you write the proper tests.
Under the hood, the various FluentAssertions methods check your values and raise exceptions when a condition is not
met. This exception is eventually caught by MS test or another test framework you may be using.
In order to change your test projects to use FluentAssertions, follow these steps:
Inside Visual Studio, open up the Package Manager Console by choosing Tools | Library Package Manager |
Package Manager Console.
1.
Select your Integration test project from the Default project drop-down (called
Spaanjaars.ContactManager45.Tests.Integration if youre following along with the walkthroughs in this
article series).
2.
In the Package Manager Console type Install-Package FluentAssertions and hit enter. 3.
Repeat step 2 and 3, three more times, but now add FluentAssertions to the Unit tests project, the 4.
11
12
13
14
15
16
17
18
public void IndexHasNoModel()
{
var controller = new HomeController();
var result = controller.Index() as ViewResult;
Assert.AreEqual(null, result.Model);
}
}
}
1 Assert.AreEqual(3, id);
1 id.Should().Be(3);
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 31 of 162
Frontend.Mvc project and the Frontend.Wcf project.
Open up the PersonTests class in the Unit Tests project and at the top of the file add the following using
statement:
5.
Change the last line of the NewPersonHasEmptyId test to the following:
With this change, the code almost reads like English; the ID of the new person created in code should be zero.
6.
Next, run your test(s) to see if everything still works. If they pass (and they should), you should see a nice
green checkmark in the Unit Test Explorer:
7.
Figure 3-6 Test Explorer Showing Green Tests
You can find out more about FluentAssertions on the projects site at CodePlex.com:
http://fluentassertions.codeplex.com/.
Stuff I Like to Do
Heres a quick list of things I like to do when it comes to unit testing:
Use FluentAssertions, as just explained. Its one of the first things I add to a Visual Studio test project.
Write a base class for all your tests and let your test classes inherit from it. Even if you dont add any behavior
yet, its useful to have all your test classes inherit a common base class to which you can add shared
functionality as you go. In the code download youll find a base class in each of the four test projects. In the
Integration tests project the base class is used to initialize the database (generated by EF) for each set of tests.
Youll see more of this in Part 5 when the database initializer is discussed.
Set up an automated build in TFS to run all your tests whenever code is checked in. This is a great way to
ensure your code is always in a valid state. For more details, see:
Professional Team Foundation Server 2012 (Ed Blankenship et al., Wrox, 2013, http://www.wrox.com
/WileyCDA/WroxTitle/Professional-Team-Foundation-Server-2012.productCd-1118314093.html)
http://msdn.microsoft.com/en-us/library/ms181716.aspx
Consider getting a Unit Test runner such as the ones supplied by ReSharper or CodeRush. Although the test
runner in Visual Studio 2012 has improved somewhat since Visual Studio 2010, I find the third party runners
easier and more powerful to work with. More details can be found here:
Unit Testing with CodeRush (http://www.devexpress.com/Products/Visual_Studio_Add-
in/Coding_Assistance/unit_test_runner.xml)
Unit Testing with ReSharper (http://www.jetbrains.com/resharper/webhelp/Unit_Testing__Index.html)
Summary
In this article you saw how to add a number of different unit test projects to your solution and how to set them up.
While you could technically add all your tests to a single unit test project, I prefer to create separate projects for
different types of tests. This allows me to decide when to run which tests. For example, because Integration tests
generally run slower than plain unit tests (because they access databases and other slow resources), I could decide to
run my unit tests after each build while the integration tests are only run when I check in code into TFS.
1 using FluentAssertions;
1 person.Id.Should().Be(0);
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 32 of 162
At this point, each test project contains a simple unit test that is used purely to check if the test projects were setup
correctly. In later parts in this article series youll see how to add more useful tests to the different test projects.
With all the plumbing done, the next step is to start building the model. In the next part in this article series youll
see how to set up the model using POCO Plain Old CLR Objects - classes. That model is then used in Part 5 that
describes how to build a repository that targets Entity Framework 5 Code First to interact with the database. In the
articles following Part 5 Ill show you how to use the model and the repositories to build various frontend applications.
Links in this Document
(1) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part03/Figure3-01_Add_New_Test_Project.png
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part03
/Figure3-03_Windows_Explorer_With_Test_Projects.png
(3) http://fluentassertions.codeplex.com/
(4) http://imar.spaanjaars.com/580/building-n-layered-applications-with-aspnet-45-part-8-putting-it-all-together-
implementing-a-wcf-45-frontend
(5) http://fluentassertions.codeplex.com/
(6) http://www.dennisdoomen.net/
ASP.NET N-Layered Applications - Making your Projects Unit Testable (Part 3)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 33 of 162
ASP.NET N-Layered Applications - Implementing a Model (Part
4)
This is Part 4 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a model using POCO classes Plain Old CLR Objects that
have no dependencies to external frameworks (such as a requirement to inherit from an Entity Framework base class).
In addition, you will see how to create unit tests for your POCO classes as well as lay a foundation for validation of
these classes.
Introduction
In Part 1 of this article series you saw a brief overview of the functionality of the ContactManager application version
4.5. Most of the functionality is very similar to the design presented in the 2.0 and 3.5 versions of my N-Layered
architecture articles.
Because the functionality is so similar, Ill skip the requirements gathering phase. Normally, when you start a new
project you dont know up front how your application and model should look. To figure out the type of application, the
underlying model and the functionality, you typically have workshops with your client to gather all the requirements.
These requirements then drive the design of the application and the model, which is a representation of the objects in
your domain that your application is going to work with. In the 2.0 version of this series
(1)
I wrote about the
requirements for the ContactManager application. Youre encouraged to check out the Design - Gathering
Requirements section in the original article to find out more about the model for that application. In the new series,
the model I use is pretty similar, as youll see in the following sections.
To learn more about how to gather requirements to design your applications and models, check out the following
publications:
http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-
1#gatheringrequirements
Practicing Domain-Driven Design (Scott Millett, under development: https://leanpub.com/Practicing-DDD)
Implementing Domain-driven Design (Vaughn Vernon, 2013, http://www.amazon.com/Implementing-Domain-
Driven-Design-Vaughn-Vernon/dp/0321834577/)
Based on the model from the previous article series, the application needs the following classes:
Class Name Description
Person This class represents a contact person used to keep track of your contacts.
Address This class represents a physical address that can be associated with a person.
EmailAddress This class represents an e-mail address of a person.
PhoneNumber This class represents a phone number of a person.
In addition to these classes, the model also needs the following types:
Type Name Type Description
PersonType Enum Defines the type of a person, such as Friend, Family or Colleague.
ContactType Enum Defines the type of the e-mail addresses and phone numbers, such as
Business or Personal.
People
EmailAddresses
PhoneNumbers
Class These classes are created to hold a collection of each of the main
entities in the model. While you could use more generic collections such
as List<T>, I prefer to create separate collections for each main type.
You will see how to create these collections later.
The following diagram shows all of these types. Later sections of this article describe the various types in more detail,
including their underlying code and place in the application.
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 34 of 162
(2) See Links in this Document at the end for the full URL of this image.
Figure 4-1 The Class Diagram for the Model project
If you look carefully at the list of types in the diagram, youll notice the collection class for Address is missing. The
reason for this is that the current application doesnt need it. The person class has two properties of type address
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 35 of 162
called HomeAddress and WorkAddress respectively. This is a change from the original design where a contact person
could have a collection of addresses as well. Ive done this to show you the concept of Value Objects which are
discussed next. Entity Framework (EF) doesnt work well with collections of Value Objects and thus I decided to add
the Address class as singular properties directly on the Person class.
Where Does the Model Fit In?
The classes defined in the Model layer flow between the concrete repositories and the user interface. The UI should
preferably not know anything, or at least as little as possible about the concrete repositories and should work with the
repository interfaces instead. If you think back about the architecture diagram from Part 1, the Model classes would be
placed between the concrete repositories and the associated interfaces and between the repository interfaces and the
UI. Figure 4-2 shows the updated diagram:
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 36 of 162
(3) See Links in this Document at the end for the full URL of this image.
Figure 4-2 Model Classes in the Architecture Diagram
Defining Your Types
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 37 of 162
Once youve identified the core types for your application, the next step is to place them in one of two groups: Entities
or Value Objects, two terms that come from the Domain Driven Design language. A lot has been written about the
differences between the two (see the links at the end of this section), so I wont repeat the complete discussion here.
Instead, Ill summarize the differences and explain what the differences mean for the ContactManager application.
An Entity is an object that is identified by a unique ID, rather than by the value it represents. The canonical example is
the Person class. If two Person instances have the same name, do you consider them to represent the same person?
Most likely not, as the name would not uniquely identify the person, and theres a high probability that even though
these instances contain the same name they refer to two different people in the real world.
A Value Object on the other hand is identified by its properties and the values they contain. The canonical example
here is Address: two instances of Address that contain the data 327 Washington Blvd Venice, California 90291 are
most likely considered the same; they dont have (or need) an identity on their own.
You can read more about the differences between Entities and Value Objects in the following articles:
http://stackoverflow.com/questions/75446/value-vs-entity-objects-domain-driven-design
http://lostechies.com/jimmybogard/2008/05/21/entities-value-objects-aggregates-and-roots/
http://devlicio.us/blogs/casey/archive/2009/02/13/ddd-entities-and-value-objects.aspx
To make the distinction in your code between these two types, its a good idea to create two base classes that your
entities can inherit from. You see how to do this next.
Creating the Infrastructure
In this section you see how to implement the Infrastructure project by creating two base classes: one for an Entity
and one for a Value Object.
Note: Ill show the implementation of a number of types step by step. That means that the code you see may not be
the final code in the project.
Creating Base Classes for Entities and Value Types
A base class for an Entity requires at least an identity property which is typically called Id, although, youre free to
make up another name. Since the base class should be reusable across multiple type definitions, its a good idea to
make the type of this Id column generic so that classes that inherit this base class can determine the actual type (for
example, an int or a Guid). The class could also have an IsTransient method that determines if the object is new
(has not been assigned an ID by the underlying database) or not. To implement this base class, I added a new class
file to the Spaanjaars.Infrastructure project, called it DomainEntity.cs and added the following code:
Heres the class diagram for the complete base class from the sample project. Ill discuss the members for comparison
and validation later.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Spaanjaars.Infrastructure
{
public abstract class DomainEntity<T>
{
/// <summary>
/// Gets or sets the unique ID of the entity in the underlying data store.
/// </summary>
public T Id { get; set; }

/// <summary>
/// Checks if the current domain entity has an identity.
/// </summary>
/// <returns>True if the domain entity is transient (i.e. has no identity yet),
/// false otherwise.
/// </returns>
public bool IsTransient()
{
return Id.Equals(default(T));
}
}
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 38 of 162
Figure 4-3 The DomainEntity<T> class
With the base class defined, I can now modify the Person class so it inherits DomainEntity and sets the type of Id to
an int. To implement that change, I modified Person in the Model project as follows:
Notice how I used DomainEntity<int> to define the type of the Id property as an int. I also removed the Id property
from the Person class as it now inherits that from the DomainEntity base class.
With the Person class done, I could now modify the NewPersonHasEmptyId test method so it now uses the
IsTransient method instead of checking for a hard-coded value of zero:
In the sample project that comes with this article series youll also see implementation code for validation inside the
DomainEntity<T> class. This is discussed later in the series.
Implementing a ValueObject base class is simpler as it doesnt require an identity. I added the following class called
ValueObject to the Spaanjaars.Infrastructure project:
Note the constraint on this type using the where clause. Although it seems to state the obvious, or even may cause a
circular reference, this code makes sure that a class that inherits ValueObject<T> can only pass itself for the T
parameter. In other words, the following is valid:
1
2
3
4
5
6
7
using Spaanjaars.Infrastructure;
namespace Spaanjaars.ContactManager45.Model
{
public class Person : DomainEntity<int>
{
}
}
1
2
3
4
5
6
[TestMethod]
public void NewPersonHasEmptyId()
{
var person = new Person();
person.IsTransient().Should().BeTrue();
}
1
2
3
public abstract class ValueObject<T> where T : ValueObject<T>
{
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 39 of 162
because the Address type passed for the T parameter does inherit ValueObject<Address>.
The following is invalid because int does not inherit ValueObject<int>:
Heres how the complete ValueObject class looks like:
Figure 4-4 The ValueObject<T> class
Ill explain the other members of this class in this and later parts in the series when I discuss modifying these classes
to implement equality comparison and validation.
Adding Properties to the Person Class
With the base class done, its time to add a few basic properties to the Person class such as a name, a type and date
of birth. Later in this article Ill modify Person once more when I add properties for the various contact details.
Before I show you the new Person class, first take a look at the two enumerations that I introduced in the beginning of
this article to define the type of a person and of a contact record. I added two new enums to a new Enums folder inside
the Model project and completed them with the following code:
1 public class Address : ValueObject<Address>
1 public class Address : ValueObject<int>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Spaanjaars.ContactManager45.Model
{
/// <summary>
/// Determines the type of a contact person.
/// </summary>
public enum PersonType
{
/// <summary>
/// Indicates an unidentified value.
/// </summary>
None = 0,

/// <summary>
/// Indicates a friend.
/// </summary>
Friend = 1,

/// <summary>
/// Indicates a family member.
/// </summary>
Family = 2,
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 40 of 162
Enum support for Entity Framework Code First has been added in version 5. Its a very useful (and much needed)
addition to the framework, as using enums is quite common. The cool thing about enums in EF is that it just works.
You dont have to define any special behaviors for your enums to roundtrip to the database correctly.
With the enums done, I completed the Person class as follows:
Here's how its Class Diagram looks:
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/// <summary>
/// Indicates a coworker.
/// </summary>
Colleague = 3
}
}

namespace Spaanjaars.ContactManager45.Model
{
/// <summary>
/// Determines the type of a contact record.
/// </summary>
public enum ContactType
{
/// <summary>
/// Indicates an unidentified value.
/// </summary>
None = 0,

/// <summary>
/// Indicates a business contact record.
/// </summary>
Business = 1,

/// <summary>
/// Indicates a personal contact record.
/// </summary>
Personal = 2
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
using System;
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
public class Person : DomainEntity<int>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public PersonType Type { get; set; }
}
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 41 of 162
Figure 4-5 The Person Class
NOTE: throughout the model classes youll find attributes on properties like this:
This marks the first name of a person as being required. These attributes are supported by EF, but it also has an
alternative available in the form of the Fluent API that enables you to configure your business rules like a required
field, a maximum length and so on, at the DbContext level rather than at the entity level. This way you can centralize
your business rules and keep the entity classes really clean. This is just a preference though; many of the validation
rules set by the API can just as well be applied using data annotation attributes such as the Required attribute. Since
the Fluent API requires a DbContext, you need to create one first. The sections Building the Object Context and
Configuring your models business rules in Part 5 will have more details. I typically apply low level attributes like
Required at the class level, and define database specific information (such as the length of a field) in the configuration
of EF.
Notice how the name of the person consists of a first name and a last name. In many places in the application the full
name of the user is displayed, so it makes sense to make a (read-only) property for that. Before I implemented the
property, I first wrote the following unit tests in the PersonTests class in the Unit Tests project:
I did not write all tests before I added the FullName property. I initially wrote the first test, and then used my
refactoring tool to implement the FullName property and have it throw a NotImplementedException. I then completed
all the other tests and implemented the property. Finally, I ran all tests to make sure they ran successfully. I needed a
few refactoring steps before the code was working as expected.
In your own projects, the order of tests and implementation may vary from topic to topic. I am not a strict test driven
developer and sometimes write the implementation first, followed by a bunch of tests to validate my code works
correctly. However, it can often be very beneficial to write tests before you write implementation, so you can focus on
the What (the public API of your code) rather than on the How (the actual implementation).
These tests ensure that the FullName property returns logical data, even if one of the fields (or both) is missing. Since
a completely empty name doesnt make a lot of sense, youll want to make one of these (or both) a required field.
Youll see later how it is done in Part 5 of this series.
With the unit tests done, I implemented the property as follows:
1
2
[Required]
public string FirstName { get; set; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[TestMethod]
public void FirstAndLastNameResultsInFullName()
{
var person = new Person() { FirstName= "Imar", LastName= "Spaanjaars" };
person.FullName.Should().Be("Imar Spaanjaars");
}

[TestMethod]
public void EmptyFirstNameReturnsLastName()
{
var person = new Person() { LastName = "Spaanjaars" };
person.FullName.Should().Be("Spaanjaars");
}

[TestMethod]
public void EmptyLastNameReturnsFirstName()
{
var person = new Person() { FirstName = "Imar" };
person.FullName.Should().Be("Imar");
}

[TestMethod]
public void AllEmptyReturnsEmpty()
{
var person = new Person();
person.FullName.Should().Be(string.Empty);
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 42 of 162
Since this is a read-only property, EF will ignore it and it wont be persisted in the database.
With the basics of the Person class done, the next step is to add classes for the contact detail records. Once those are
done, Ill revisit the Person class again and add properties for addresses, phone numbers and e-mail addresses.
Adding the Contact Detail Classes
As you saw earlier in this article, the Person class has a few properties that contain contact information. For the
contact data, the project needs the following three classes:
Address
PhoneNumber
EmailAddress
For this article series, I implemented Address as a ValueObject and the other two as entities. You could argue that
PhoneNumber and EmailAddress are great candidates for Value Objects and I would fully agree. However, I want to
implement these types as collections (so you can have multiple instances of each attached to a contact person). To
implement this one to many relationship in EF, the other end (i.e. the PhoneNumber and the EmailAddress) needs to
have its own identity (e.g. an Id property). That conflicts with the absence of an identity in a ValueObject, and as
such PhoneNumber and EmailAddress are implemented as entities. For these three classes, the sample project
contains the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public string FullName
{
get
{
string temp = FirstName ?? string.Empty;
if (!string.IsNullOrEmpty(LastName))
{
if (temp.Length > 0)
{
temp += " ";
}
temp += LastName;
}
return temp;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// PhoneNumber
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
public class PhoneNumber : DomainEntity<int>
{
[Required]
public string Number { get; set; }
public ContactType { get; set; }
public Person Owner { get; set; }
public int OwnerId { get; set; }
}
}

// EmailAddress
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
public class EmailAddress : DomainEntity<int>
{
[Required]
[EmailAddressAttribute]
public string EmailAddressText { get; set; }
public ContactType { get; set; }
public Person Owner { get; set; }
public int OwnerId { get; set; }
}
}

ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 43 of 162
EmailAddress and PhoneNumber participate in a one to many relationship: one Person can have zero to many
instances of type EmailAddress and PhoneNumber. To create the relationship, I added the Owner property to these two
classes. This way you can assign a person to these classes and link back to the Person from an EmailAddress or
PhoneNumber. Besides the Ower property, I also added an OwnerId property of type int. EF supports "foreign key
properties
(4)
" which let you assign one entity to another simply by using its ID. So for example, rather than doing
this:
you can assign the ID directly like this:
This could save you from an additional call to the database when you only have the person's ID available (for example,
when creating a new EmailAddress in a Web Form where the ID of the person is passed in the query string).
Obviously, you can still assign the Owner property a value if you happen to have a valid instance of Person.
The class diagram for the three classes with contact details looks as follows:
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Address
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
public class Address : ValueObject<Address>, IValidatableObject
{
private Address() { }

public Address(string street, string city, string zipCode,
string country, ContactType contactType)
{
Street = street;
City = city;
ZipCode = zipCode;
Country = country;
ContactType = contactType;
}

public string Street { get; private set; }
public string ZipCode { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
public ContactType { get; private set; }

public bool IsNull
{
get
{
return (string.IsNullOrEmpty(Street) && string.IsNullOrEmpty(ZipCode)
&& string.IsNullOrEmpty(City) && string.IsNullOrEmpty(Country));
}
}
}
}
1
2
var emailAddress = new EmailAddress { ... };
emailAddress.Owner = _personRepository.FindById(123);
1
2
var emailAddress = new EmailAddress { ... };
emailAddress.OwnerId = 123;
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 44 of 162
Figure 4-6 The Address, EmailAddress and PhoneNumber classes
Note: The IHasOwner interface and Validate methods are discussed later in this article.
EmailAddress and PhoneNumber inherit DomainEntity<int> which gives them an Id property of type int. Address
inherits ValueObject<Address> which makes it a value object. For value objects, its a good practice to make them
immutable. That means that once youve created an instance of an object and filled it with data through the
constructor, you shouldnt be able to change it anymore. This is easily accomplished with a constructor that has
parameters for all properties of the class, like this:
In addition, the setters of the properties have been marked private so they are only accessible from within the class:
And finally, in order for the Entity Framework to create instances of Address, it needs a parameterless constructor.
This breaks the POCO requirements somewhat as you must implement this constructor to support EF. However, the
constructor can be made private, so its not accessible by regular external code.
Personally, I am fine with this requirement as I feel it doesnt break my model design.
Dealing with Collections
When dealing with collections and Entity Framework, theres something to be aware off. When you add entities to a
collection that is tracked by Entity Framework (for example, because the parent of the collection has been added to
the context) they are automatically added to the context and thus to the database. Consider this example:
1
2
3
4
5
6
7
8
9
public Address(string street, string city, string zipCode,
string country, ContactType contactType)
{
Street = street;
City = city;
ZipCode = zipCode;
Country = country;
ContactType = contactType;
}
1 public string Street { get; private set; }
1 private Address() { }
1 var person = new Person();
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 45 of 162
When this code executes, EF inserts two new records: one in the Person table and one in the EmailAddresses table.
The row in the EmailAddresses table will have a foreign key pointing to the Person table (if this is all new to you,
dont worry yet; Ill dig deeper into this in Part 5).
However, if you try to remove an EmailAddress, things work a bit differently. Consider this code:
This code retrieves an existing person, clears the EmailAddresses collection and then saves the changes. What you
might expect to happen is that the e-mail addresses that were previously assigned to the person are actually deleted
from the database. This is, however, not the case. The only thing that happens is that EF clears the foreign key that
points to the person. In other words, the e-mail address itself is not deleted from the database; it just no longer points
to the Person row.
If you Google for this problem you find many solutions that show you how to mark the EmailAddress objects as
deleted by setting their EntityState property to Deleted. However, as youll see later, you wont have direct access to
the EF data context from the locations where youre removing e-mail addresses from the Persons EmailAddresses
collection. This is, however, relatively easy to fix in the DbContext itself as youll see in Part 5. In order for the
DbContext to understand which objects it should remove, you can let these entities implement a custom interface that
you can detect in the DbContext and take the appropriate action. Again, Part 5 shows how to implement the code in
the DbContext so for now Ill just show you the interface that the removable objects implement:
EmailAddress and PhoneNumber then implement this interface:
The interface is implemented by the Owner property (shown earlier) in each of the two classes. Youll see this interface
again in Part 5.
If you look in the sample code that comes with this article series, youll notice that these classes contain more code.
Most of that code is related to validation, which is discussed in Part 5.
With the classes added to the project, I could write a few simple unit tests that demonstrate I can instantiate these
classes and set their properties. However, most of that would come down to testing the .NET framework (do property
getters and setters work for example) rather than testing my own code. Ill write unit and integration tests for these
classes later to test concepts like validation, which should implicitly cover instantiating and using these objects.
Therefore, I am not adding any more tests for now.
Implementing Equality Comparison
When working with a model, youre going to need the ability to compare two instances of a class in your model with
each other. You could have an instance of a Person that you want to compare with an existing instance that is being
submitted to your application using a WCF service for example. Or you may want to see if a persons personal address
2
3
4
person.EmailAddresses.Add(new EmailAddress { EmailAddressText = "[email protected]" });
myContext.People.Add(person);
myContext.SaveChanges();
1
2
3
var person = myContext.People.First(x => x.Id = id);
person.EmailAddresses.Clear();
myContext.SaveChanges();
1
2
3
4
5
6
7
public interface IHasOwner
{
/// <summary>
/// The Person instance this object belongs to.
/// </summary>
Person Owner { get; set; }
}
1
2
3
4
5
6
7
public class EmailAddress : DomainEntity<int>, IHasOwner
{
}

public class PhoneNumber : DomainEntity<int>, IHasOwner
{
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 46 of 162
is the same has her business address.
The default implementation for comparison of classes in .NET is to use reference equality; in other words, .NET checks
if two references are pointing to the same object. Consider this example (which you find in the PersonTests class
inside the Unit Tests project):
When you run this test now, it fails. The variables person1 and person2 are referring to two different instances of
Person. This means that the equality check (==) returns false.
However, it would make perfect sense if the check returned true since Person is an Entity whose identity and
uniqueness is defined by the Id property. Both Person instances have the same ID, so from an application perspective,
they should be considered the same.
In contrast, two Addresses (implemented as Value Types) should be considered the same when the values for all of
their properties match. Consider this test (that I added to the AddressTests class inside the Unit Tests project):
Again, when you run this test it would fail. The variables address1 and address2 each refer to a different instance.
The default of the == operator for objects is to check reference equality, and so these two objects are not considered
the same.
To fix these issues, and have .NET consider your entities to be the same if they have the same ID and consider your
Value Objects to be the same when all of their properties match, you need to override Equals and the equality and
inequality operators (== and !=).
For both implementations, I borrowed code from the Domain Oriented N-Layered .NET 4.0 Sample App (at
http://microsoftnlayerapp.codeplex.com/), a sample application and reference guide for implementing N-Layered
applications in .NET. While there is some overlap between this guide and mine, youll find the Microsoft version is more
complex and extensive, and much more geared towards large enterprise-scale applications.
Their sample application contains an implementation to compare Value Objects that uses reflection if necessary.
Implementing their code into my ValueObject<T> class results in the following code:
1
2
3
4
5
6
7
[TestMethod]
public void TwoPeopleWithSameIdAreTheSame()
{
var person1 = new Person { Id = 1, FirstName = "Imar", LastName = "Spaanjaars" };
var person2 = new Person { Id = 1, FirstName = "Imar", LastName = "Spaanjaars" };
(person1 == person2).Should().BeTrue();
}
1
2
3
4
5
6
7
[TestMethod]
public void TwoIdenticalAddressesShouldBeTheSame()
{
var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
(address1 == address2).Should().BeTrue();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class ValueObject<T> :
IEquatable<T> where T : ValueObject<T>, IValidatableObject
{
public abstract IEnumerable<ValidationResult> Validate(
ValidationContext validationContext);

public IEnumerable<ValidationResult> Validate()
{
var validationErrors = new List<ValidationResult>();
var ctx = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, ctx, validationErrors, true);
return validationErrors;
}

private bool CheckValue(PropertyInfo p, T other)
{
var left = p.GetValue(this, null);
var right = p.GetValue(other, null);
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 47 of 162
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
if (left == null || right == null)
{
return false;
}

if (typeof(T).IsAssignableFrom(left.GetType()))
{
return ReferenceEquals(left, right);
}
return left.Equals(right);
}

public bool Equals(T other)
{
if ((object)other == null)
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

//compare all public properties
PropertyInfo[] publicProperties = GetType().GetProperties();

if (publicProperties.Any())
{
return publicProperties.All(p => CheckValue(p, other));
}
return true;
}

public override bool Equals(object obj)
{
if ((object)obj == null)
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;

}
var item = obj as ValueObject<T>;

if ((object)item != null)
{
return Equals((T)item);
}
return false;
}

public override int GetHashCode()
{
int hashCode = 31;
bool changeMultiplier = false;
int index = 1;

PropertyInfo[] publicProperties = this.GetType().GetProperties();

if (publicProperties.Any())
{
foreach (var item in publicProperties)
{
object value = item.GetValue(this, null);

if ((object)value != null)
{
hashCode = hashCode * ((changeMultiplier) ? 59 : 114) + value.GetHashCode();
changeMultiplier = !changeMultiplier;
}
else
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 48 of 162
This code contains a version of Equals that checks if the value compared against is null. If its not, it then checks if
both sides are referring to the same instance, and if thats not the case, it uses reflection to compare each individual
property. It also overrides the == (equals) and != (not equals) operators by calling the Equals method. Finally, it
overrides GetHashCode to generate a value for the object used in hash tables, again using reflection.
If you dont like the reflection implementation, you can always override Equals (object obj) in the Address class (or
any other class that inherits ValueObject) and compare its properties directly.
The DomainEntity base class requires a slightly different approach: it only needs to compare the IDs of the two
objects, taking nullability and a transient state into account as well. Heres the full implementation of that class:
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
{
hashCode = hashCode ^ (index * 13);
//only for support {"a",null,null,"a"} <> {null,"a","a",null}
}
}
}
return hashCode;
}

public static bool operator ==(ValueObject<T> left, ValueObject<T> right)
{
if (Equals(left, null))
{
return (Equals(right, null)) ? true : false;
}
return left.Equals(right);
}

public static bool operator !=(ValueObject<T> left, ValueObject<T> right)
{
return !(left == right);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public abstract class DomainEntity<T> : IValidatableObject
{
public T Id { get; set; }

public bool IsTransient()
{
return Id.Equals(default(T));
}

public override bool Equals(object obj)
{
if (obj == null || !(obj is DomainEntity<T>))
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;
}

var item = (DomainEntity<T>)obj;

if (item.IsTransient() || IsTransient())
{
return false;
}
return item.Id.Equals(Id);
}

public override int GetHashCode()
{
if (!IsTransient())
{
return Id.GetHashCode() ^ 31;
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 49 of 162
Again, Equals checks if the other side is null or not a DomainObject<T> (in which case they should never be
considered the same). It also checks if the two references are not actually the same instance. If thats not the case,
the code checks if one of the objects (or both) is in a transient state:
If one of them (or both) is transient, the code assumes they are not equal. This is necessary when creating new
objects. Without that check, all new objects that havent saved in the database would be considered equal which of
course is not correct.
If none of the conditions above are met, the code checks the Id property of both objects. If they are the same, the
objects are considered equal. Otherwise they are considered to be different.
The following set of Unit Tests demonstrate the behavior of this implementation. These are just a few samples to show
the general concept; the code that comes with this article has other tests to cover additional scenarios.
The following piece of code shows some of the tests for the DomainEntity classes:
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
return base.GetHashCode();
}

public static bool operator ==(DomainEntity<T> left, DomainEntity<T> right)
{
if (Equals(left, null))
return (Equals(right, null)) ? true : false;
else
return left.Equals(right);
}

public static bool operator !=(DomainEntity<T> left, DomainEntity<T> right)
{
return !(left == right);
}

public abstract IEnumerable<ValidationResult> Validate(
ValidationContext validationContext);

public IEnumerable<ValidationResult> Validate()
{
var validationErrors = new List<ValidationResult>();
var ctx = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, ctx, validationErrors, true);
return validationErrors;
}
}
1
2
3
4
if (item.IsTransient() || IsTransient())
{
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[TestClass]
public class DomainEntityTests
{
#region Nested helper classes

internal class PersonWithIntAsId : DomainEntity<int>
{ }

internal class PersonWithGuidAsId : DomainEntity<Guid>
{ }

#endregion

[TestMethod]
public void TransientLeftIsNotEqual()
{
var personLeft = new PersonWithIntAsId();
var personRight = new PersonWithIntAsId { Id = 1 };
personLeft.Equals(personRight).Should().BeFalse();
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 50 of 162
Similarly, I have tests for the ValueObject class. In the examples below, I use the Address class (that inherits
ValueObject) but in the code download you find a few other tests as well.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

[TestMethod]
public void TwoTransientsAreNotEqual()
{
var personLeft = new PersonWithIntAsId();
var personRight = new PersonWithIntAsId();
personLeft.Equals(personRight).Should().BeFalse();
}

[TestMethod]
public void NewPersonWithIntAsIdIsTransient()
{
var person = new PersonWithIntAsId();
person.IsTransient().Should().BeTrue();
}

[TestMethod]
public void PersonWithIntAsIdWithValueIsNotTransient()
{
var person = new PersonWithIntAsId { Id = 4 };
person.IsTransient().Should().BeFalse();
}

[TestMethod]
public void NewPersonWithGuidAsIdIsTransient()
{
var person = new PersonWithGuidAsId();
person.IsTransient().Should().BeTrue();
}

[TestMethod]
public void PersonWithGuidAsIdWithValueIsNotTransient()
{
var person = new PersonWithGuidAsId { Id = Guid.NewGuid() };
person.IsTransient().Should().BeFalse();
}

[TestMethod()]
public void EntitiesWithSameIdentityShouldBeEqual()
{
var entityLeft = new PersonWithIntAsId { Id = 1 };
var entityRight = new PersonWithIntAsId { Id = 1 };

bool resultOnEquals = entityLeft.Equals(entityRight);
bool resultOnOperator = entityLeft == entityRight;

resultOnEquals.Should().BeTrue();
resultOnOperator.Should().BeTrue();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[TestClass]
public class AddressTests
{
[TestMethod]
public void TwoIdenticalAddressesShouldBeTheSame()
{
var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
(address1 == address2).Should().BeTrue();
}

[TestMethod]
public void DifferentAddressesShouldNotBeTheSame()
{
var address1 = new Address("Some other street", "City", "ZipCode", "Country",
ContactType.Business);
var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
(address1 != address2).Should().BeTrue();
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 51 of 162
With the tests added to the Unit Test project, the next step is modelling collections.
Creating Collections
When modelling collections, you have a few different options. For example, its quite common to use a List<T> class
to store collections of objects. Using that class, you could give Person access to a collection of EmailAddress instances
like this:
You can then add instances of EmailAddress to the EmailAddresses collection like this:
While this works great, its generally not recommended to expose List<T> in the public API of a class. List<T> is
designed for performance, and not meant for inheritance. This means you cant override any of its members that
change the way the class behaves when it comes to adding, finding and removing members. This makes it impossible
to add specialized behavior to your collection; something you often want to do. More information about this guideline
can be found here:http://msdn.microsoft.com/en-us/library/ms182142%28v=vs.110%29.aspx
It is recommended that you implement a class that inherits Collection<T> instead, which is what I have done in the
sample project. The downside of inheriting that class is that you miss out on some of the useful functionality that
List<T> has. For example, Collection<T> does not have a method to sort the data, or to quickly add a range.
However, that behavior is easy to add to a base class, so the other collections in your project can get it for free. In the
Spaanjaars.ContactManager application, I have added the following CollectionBase<T> class:
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

[TestMethod]
public void InstanceOfValueObjectDoesNotEqualNull()
{
var address1 = new Address();
address1.Equals(null).Should().BeFalse();
}

[TestMethod]
public void ReferenceEqualsIsEqual()
{
var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
Address address2 = address1;
address1.Equals(address2).Should().BeTrue();
}
}
1
2
3
4
5
6
7
8
public class Person : DomainEntity<int>
{
public string FirstName { get; set; }

// Other properties here

public List<EmailAddress> EmailAddresses { get; set; }
}
1
2
3
var person = new Person();
person.EmailAddresses.Add(new EmailAddress {ContactType = ContactType.Business,
EmailAddressText = "[email protected]"});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class CollectionBase<T> : Collection<T>, IList<T>
{
protected CollectionBase() : base(new List<T>()) { }

protected CollectionBase(IList<T> initialList) : base(initialList) { }

protected CollectionBase(CollectionBase<T> initialList) : base(initialList) { }

public void Sort(IComparer<T> comparer)
{
var list = Items as List<T>;
if (list != null)
{
list.Sort(comparer);
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 52 of 162
The class is marked as abstract which means you cant create instances of it directly. Its sole purpose is to serve as a
base class for other collections. It inherits Collection<T> as per the recommendation which gives it virtual members
such as InsertItem, RemoveItem, SetItem and ClearItems. Notice that Collection<T> implements the IList<T>
interface so you can pass instances of classes that inherit Collection<T> to any member that expects an IList<T>.
The class has three constructors that all call the base constructor with an initial list. Notice how the default constructor
calls the base constructor with a new instance of List<T>:
Although you shouldnt expose members of List<T> in your public API, its perfectly OK to use one internally.
Besides the constructors, the class exposes two methods to sort the underlying data and a method to add ranges of
instances with a single call:
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
}
}

public void Sort()
{
var list = Items as List<T>;
if (list != null)
{
list.Sort();
}
}

public void AddRange(IEnumerable<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection", "Parameter collection is null.");
}
foreach (var item in collection)
{
Add(item);
}
}
}
1
2
3
protected CollectionBase()
: base(new List<T>())
{ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void Sort(IComparer<T> comparer)
{
var list = Items as List<T>;
if (list != null)
{
list.Sort(comparer);
}
}

public void Sort()
{
var list = Items as List<T>;
if (list != null)
{
list.Sort();
}
}

public void AddRange(IEnumerable<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection", "Parameter collection is null.");
}
foreach (var item in collection)
{
Add(item);
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 53 of 162
This base class is used by all collections in the project: for People, EmailAddresses, and PhoneNumbers. Heres an
example of the EmailAddresses collection:
With this class in the project, the Person class can now be rewritten like this:
Notice how the code for the property now refers to EmailAddresses twice: the first reference is the collections type,
the second one the name of the property. I also instantiate a new instance of this class in the Person's constructor so
it's ready for use.
Adding instances of EmailAddress remains the same:
What I like about this setup is that its now very easy to add specialized behavior to these collections. Rather than
forcing users of your API to manually construct and initialize an EmailAddress, you could add a convenience method
for Add on the EmailAddresses collection like this:
Adding an e-mail address can now be as simple as this:
28
29
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace Spaanjaars.ContactManager45.Model.Collections
{
public class EmailAddresses : CollectionBase<EmailAddress>
{
public EmailAddresses() { }

public EmailAddresses(IList<EmailAddress> initialList)
: base(initialList)
{ }

public EmailAddresses(CollectionBase<EmailAddress> initialList)
: base(initialList)
{ }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person : DomainEntity<int>
{
public Person()
{
EmailAddresses = new EmailAddresses();
}

public string FirstName { get; set; }

// Other properties here

public EmailAddresses EmailAddresses { get; set; }
}
1
2
3
var person = new Person();
person.EmailAddresses.Add(new EmailAddress {ContactType = ContactType.Business,
EmailAddressText = "[email protected]"});
1
2
3
4
public void Add(string emailAddressText, ContactType contactType)
{
Add(new EmailAddress { ContactType = contactType, EmailAddressText = emailAddressText });
}
1
2
Person person = new Person();
person.EmailAddresses.Add("[email protected]", ContactType.Business);
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 54 of 162
Once I added the collection classes to the project, I was able to write tests like the following to verify the behavior of
the AddRange and Sort methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Model;
using Spaanjaars.ContactManager45.Model.Collections;

namespace Spaanjaars.ContactManager45.Tests.Unit
{
[TestClass]
public class CollectionBaseTests
{
[TestMethod]
public void NewCollectionUsingNewListsAddsValues()
{
var collection = new IntCollection(new List<int> { 1, 2, 3 });
collection.Count.Should().Be(3);
}

[TestMethod]
public void NewCollectionUsingExistingCollectionAddsValues()
{
var collection1 = new IntCollection(new List<int> { 1, 2, 3 });
var collection2 = new IntCollection(collection1);
collection2.Count.Should().Be(3);
}

[TestMethod]
public void UsingAddRangeAddsValues()
{
var collection1 = new IntCollection(new List<int> { 1, 2, 3 });
var collection2 = new IntCollection();
collection2.AddRange(collection1);
collection2.Count.Should().Be(3);
}

[TestMethod]
public void SortPeopleWithSpecifiedComparerSortsCorrectly()
{
var people = new People();
people.Add(new Person { FirstName = "John", LastName = "Doe" });
people.Add(new Person { FirstName = "Imar", LastName = "Spaanjaars" });
people.Add(new Person { FirstName = "Jane", LastName = "Doe" });

people.Sort(new PersonComparer());

people[0].FullName.Should().Be("Imar Spaanjaars");
people[1].FullName.Should().Be("Jane Doe");
people[2].FullName.Should().Be("John Doe");
}

[TestMethod]
public void SortIntsSorts()
{
var ints = new IntCollection { 3, 2, 1 };
ints.Sort();
ints[0].Should().Be(1);
ints[1].Should().Be(2);
ints[2].Should().Be(3);
}
}

internal class IntCollection : CollectionBase<int>
{
public IntCollection()
{ }

public IntCollection(IList<int> initialList)
: base(initialList)
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 55 of 162
Most of this is pretty straight forward, and by looking at the test name and implementation you should be able to see
what the code is testing. I added a helper class called IntCollection to test the Sort behavior for classes that
implement IComparable (which makes it possible to sort a collection of a type without specifying a special Comparer
classes).
The thing that may be new to you is the PersonComparer, a class dedicated to defining how instances of Person
should be sorted. In this implementation, they are sorted on their FullName property, but you could of course change
that if you want by changing the implementation of the Compare method or by implementing a completely different
Comparer class altogether. Using this implementation of PersonComparer, you can sort a collection of people like this:
After this code has run, the collection now contains the people ordered by their full name, which means my name is
listed first, followed by Jane and Joe.
The final thing I like to implement in my model is the ability to automatically keep track of the date and time objects
were created and modified. Youll see how I implemented this in the model next, while the article on building an Entity
Framework repository shows how to automatically update these dates and save them in the database.
Automatic Tracking of Creation and Modification Dates
Its common that you want to keep track of the date and time an object was created and last modified. To this end,
you could add two DateTime properties to each class that you want to track like this:
Then whenever you create a new instance of Person, you can fill in the DateCreated using a constructor:
In addition, whenever youre modifying an instance of Person, you can update the DateModified property:
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
{ }

public IntCollection(CollectionBase<int> initialList)
: base(initialList)
{ }
}

public class PersonComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.FullName.CompareTo(y.FullName);
}
}
}
1
2
3
4
5
var people = new People();
people.Add(new Person { FirstName = "John", LastName = "Doe" });
people.Add(new Person { FirstName = "Imar", LastName = "Spaanjaars" });
people.Add(new Person { FirstName = "Jane", LastName = "Doe" });
people.Sort(new PersonComparer());
1
2
3
4
5
6
public class Person : DomainEntity<int>
{
// Other properties here.
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
1
2
3
4
5
6
7
public class Person : DomainEntity<int>, IDateTracking
{
public Person()
{
DateCreated = DateTime.Now;
}
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 56 of 162
However, this gets repetitive and boring after a while and because you need to do this every time you make a change
to a person, theres a fair chance you forget to implement this code.
I prefer a different solution to the problem that works like this:
I create an interface called IDateTracking that defines two read/write properties for the date and time an
object was created and last modified.
1.
I let each of the objects I want to track implement this interface and add the two properties to the class to
satisfy the contract specified by this interface.
2.
In my Entity Framework DbContext that saves new and modified objects to the database, I detect objects that
implement this interface and then automatically update the correct properties with the current date and time.
3.
Implementing step 1 and 2 is really easy; youll see how to do this next. Step 3 is discussed in the next article in this
series when the EF DbContext is discussed.
Heres the code for the interface I added to the Model project and namespace:
This interface defines two read/write properties for the creation and modification dates. Implementing this interface in
an entity is straightforward as well. Heres the code for the Person class:
You can now assign DateCreated a value in the constructor to keep track of the date an object was created. When an
existing data is retrieved from the database, that property is overwritten with the value from the database, giving you
the correct date and time. You can now also manually set the DateModified property whenever you change the
object. However, as youll see in the next article, you can let EF automatically manage these two properties for you.
Putting it All Together
So far youve seen the code for some simple classes that mostly consist of just a number of straightforward
automatically implemented properties. However, in order to make the model more useful, you should create
relationships between the various classes. For example, a Person should be given collection classes for the various
contact details such as EmailAddress and PhoneNumber classes. Also, Person needs properties for address details such
as HomeAddress and WorkAddress. To make the API easier to work with, all these properties should be instantiated in
1 myPerson.DateModified = DateTime.Now;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;

namespace Spaanjaars.ContactManager45.Model
{
/// <summary>
/// Defines an interface for objects whose creation and modified
/// dates are kept track of automatically.
/// </summary>
public interface IDateTracking
{
/// <summary>
/// Gets or sets the date the object was created.
/// </summary>
DateTime DateCreated { get; set; }

/// <summary>
/// Gets or sets the date the object was last modified.
/// </summary>
DateTime DateModified { get; set; }
}
}
1
2
3
4
5
6
7
public class Person : DomainEntity<int>, IDateTracking
{
// Other code here

public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 57 of 162
the constructor so you can access them immediately after you constructed a new Person.
Heres the revised code for the Person class with the new properties and constructor code. Note: the code that comes
with the article has full XML comments on all public members.
With this setup, you can now write tests that confirm the properties have been set up correctly (and that demonstrate
the usage of the API quite nicely):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System;
using System.Collections.Generic;
using Spaanjaars.ContactManager45.Model.Collections;
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
public class Person : DomainEntity<int>, IDateTracking
{
public Person()
{
EmailAddresses = new EmailAddresses();
PhoneNumbers = new PhoneNumbers();
HomeAddress = new Address(null, null, null, null, ContactType.Personal);
WorkAddress = new Address(null, null, null, null, ContactType.Business);
}

[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public PersonType Type { get; set; }
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
public EmailAddresses EmailAddresses { get; set; }
public PhoneNumbers PhoneNumbers { get; set; }

public string FullName
{
get
{
string temp = FirstName ?? string.Empty;
if (!string.IsNullOrEmpty(LastName))
{
if (temp.Length > 0)
{
temp += " ";
}
temp += LastName;
}
return temp;
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[TestMethod]
public void CanAddEmailAddressToNewPerson()
{
var person = new Person();
person.EmailAddresses.Add(new EmailAddress());
person.EmailAddresses.Count.Should().Be(1);
}

[TestMethod]
public void CanAddPhoneNumberToNewPerson()
{
var person = new Person();
person.PhoneNumbers.Add(new PhoneNumber());
person.PhoneNumbers.Count.Should().Be(1);
}

ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 58 of 162
Defining Repository Interfaces
The final code that needs to be added to the Model project is the definition of the interfaces for the repositories. In
Part 1 of this series I briefly introduced the IRepository<T, K> interface that defines the contract that a repository
class should implement to enable CRUD (Create, Read, Update and Delete) behavior. In my project, I placed the
IRepository<T, K> in the Spaanjaars.Infrastructure project, so I can easily reuse it across multiple applications. I
then added the following code;
Notice how this interface uses generics with two type parameters: T and K. T is used for the actual entity type (such as
Person) while K is used for its key. The key is usually an int or a Guid. These types are then used in the interface
members to define the parameter or return type of each method. Youll see a more concrete example shortly.
The interface defines the following methods:
Member name Description
Add (returns void) Adds an object to the underlying data source. How this is
done depends on the underlying framework. The EF
implementation adds it to the EF DbContext so its added
to the SQL Server database whenever the changes are
saved.
FindAll (returns an IQueryable of T or an IEnumerable
of T)
Returns all requested objects in the underlying source.
One of its overloads enables you to define a search
expression. Both overloads accept a parameter to define
which properties you want to eager load, as youll see
later.
FindById (returns an instance of T) Returns an instance of T by its unique ID in case its
found, or null otherwise.
Remove (returns void) Removes an object from the underlying data source. How
this is done depends on the underlying framework. The
EF implementation removes it from the EF DbContext so
its also removed from the SQL Server database
17
18
19
20
21
22
23
24
25
26
27
28
29
[TestMethod]
public void NewPersonHasInstantiatedWorkAddress()
{
var person = new Person();
person.WorkAddress.Should().NotBeNull();
}

[TestMethod]
public void NewPersonHasInstantiatedHomeAddress()
{
var person = new Person();
person.HomeAddress.Should().NotBeNull();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Spaanjaars.Infrastructure
{
public interface IRepository<T, K> where T : class
{
T FindById(K id, params Expression<Func<T, object>>[] includeProperties);
IQueryable<T> FindAll(params Expression<Func<T, object>>[] includeProperties);
IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate,
params Expression<Func<T, object>>[] includeProperties);
void Add(T entity);
void Remove(T entity);
void Remove(K id);
}
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 59 of 162
whenever the changes are saved.
By implementing the Add and Remove methods of this interface you can add and remove items from the underlying
data source. The Remove method has an overload that accepts the unique ID of the object to make it easy to remove
an entity without having a full instance at hand. Selecting is done using FindById (that returns a single instance) and
FindAll (that returns a collection). Both methods accept a params array called includeProperties. This is used to
dynamically include related entities (such as PhoneNumbers when accessing a person.) You see how this works in the
next part in this series when the EF repository is explored. The overload of FindAll that returns an IEnumerable<T>
has a parameter called predicate that looks like this: Expression<Func<Person, bool>>. Although it looks pretty
scary with the nested generics, using it is pretty simple. As an example, heres how you could search for all contact
people of a specific type:
You can also use multiple criteria at the same time. For example:
Youll see more of the repository implementation later. For now all thats important to realize is that the FindAll
method lets you specify complex search criteria.
Finally, updating is done by retrieving one or more existing items, and then updating the objects properties. When
saving the changes using an EF DbContext, EF will automatically persist the changes into the database.
For the ContactManager application, I have one class that implements this interface: a PersonRepository to manage
contact people. Rather than implementing this interface directly in my repositories, I created another interface that
inherits IRepository<T, K>, like this:
Although I havent added any members to this interface yet (other than those it inherits from the generic repository
interface), it lays a nice foundation for future updates. Imagine I want to add a FindByLastName method to the
PeopleRepository. I could add that member to IRepository instead, forcing my concrete implementations to
implement this member as well. However, that method would have no meaning to other repositories you may add to
your system. So by adding an intermediate interface you get the best of both worlds: IPeopleRepository can do
anything IRepository can, but its still open to be expanded with methods that only make sense to a
PeopleRepository.
My concrete PeopleRepository implements this interface as youll see in Part 5. Note that I am closing the generic
type by explicitly specifying an int for the K type parameter. The Person class has been set up to use an int for the
Id property as well (public class Person : DomainEntity<int>, IDateTracking) so it makes sense to make the
repositories specific for an int as well.
With these interfaces, a method on an actual concrete repository to manage people in the system could look like this:
The method accepts an int for the ID (as specified by the int type on the IPeopleRepository) and returns a Person
because IPeopleRepository specifies Person as the type of the T type parameter which is used as the return type of
the FindById method in the generic IRepository interface. As youll see in the next article, the actual implementation
is slightly different because FindById is implemented in a generic repository.
1 var colleagues = repository.FindAll(x => x.Type == PersonType.Colleague);
1
2
var friendsNameMaryJane = repository.FindAll(
x => x.FirstName == "Mary Jane" && x.Type == PersonType.Friend);
1
2
3
public interface IPeopleRepository : IRepository<Person, int>
{
}
1
2
3
4
5
public Person FindById(int id,
params Expression<Func<Person, object>>[] includeProperties)
{
// Implementation here
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 60 of 162
The actual code (such as an MVC controller, a Web Forms page, or a Unit Test) would work with instances of the
IPeopleRepository interface to get and update data in the database. Heres an example of the Delete method of a
controller in an MVC application that accepts the ID of the object and deletes it by calling Remove on the concrete
repository:
Here, _peopleRepository is an object that implements the IPeopleRepository interface. In the MVC project, this
instance is injected using StructureMap but you can of course also instantiate an object yourself.
The UnitOfWorkFactory code is explained in the next article in this series, and youll find full details on implementing
an MVC frontend in Part 6 and details on a Web Forms implementation in Part 7 of this series.
Stuff I Like to Do
Just as in the previous article in this series, Ill provide a quick list of things I like to do when building a model. Again, I
wont be providing a lot of detail, but instead mention a few items I like or consider best practices.
Implement a base class for collections. This way you can centralize the behavior for all your collections.
Let your custom collections inherit from the collection base class and dont use List<T> in the public API of
your object model.
Write extensive unit tests for your model classes. The Model project is now still relatively small, so you should
be able to achieve great code coverage. Once you start expanding the model project itll be relatively easy to
maintain a high code coverage. However, the lower the coverage, the less inclined youll be to catch up later.
Document the public members of your API using XML comments (http://msdn.microsoft.com/en-us/library
/b2s063f7.aspx). For example, members in the various interfaces and classes should be documented to make it
easier to work with them later in the project. You can force the compiler to generate an XML file with the
comments as well as list all items you forgot to document as compilation warnings by checking off the XML
documentation file checkbox on the Build category if the projects Properties dialog, shown in Figure 4.7:
(5) See Links in this Document at the end for the full URL of this image.
Figure 4-7 The Project Properties Dialog
I typically only do this for the release build so I am not cluttering the list with compile warnings too much.
1
2
3
4
5
6
7
8
9
[HttpDelete]
public ActionResult Delete(int id)
{
using (_unitOfWorkFactory.Create())
{
_peopleRepository.Remove(id);
}
return RedirectToAction("Index");
}
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 61 of 162
Summary
In this article you saw how to build up the model for the application. If youre familiar with previous versions of my
N-Layer Design article series, youll recognize a lot of stuff. Even if youre unfamiliar with those articles, the code in the
Model project should be easy to follow: most of it comes down to simple POCO classes like Person, and a bunch of
collection classes to support collections of the POCO classes. The most complex code is probably the equality comparer
code in the two base classes in the Infrastructure project. However, this is plumbing code you only need to write
once, and not maintain during normal development of your application.
In previous versions of this article series targeting .NET 2 and 3.5, the class design part of this setup was pretty easy
to implement. All you had to do was creating the class and add the relevant properties for the types to them. However,
it was the database part that was really hard to set up and required a lot of manually written code, stored procedures
and testing. Fortunately, with EF Code First this is now really easy to implement as youll see in the next installment of
this article series.
Links in this Document
(1) http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part04/Figure4-1_Model_Full_Class_Diagram.png
(3) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part04/Figure4-2_Model_Architecture.png
(4) http://msdn.microsoft.com/en-us/data/jj713564.aspx
(5) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part04
/Figure4-7_Project_Properties_for_XML_File.png
ASP.NET N-Layered Applications - Implementing a Model (Part 4)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 62 of 162
ASP.NET N-Layered Applications - Implementing a Repository
using EF Code First (Part 5)
This is Part 5 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a concrete implementation of the repository that was
introduced in the preceding article. Ill show you how to create a data access layer that targets the Entity Framework
(EF) and implements the repository interface in a clean and maintainable way.
Note: this article uses the Entity Framework as thats my ORM of choice. However, you can use many of these
principles using a different ORM such as NHibernate
(1)
. The applications in the presentation layer wouldnt know the
difference; they are just programmed to consume the various interfaces without ever knowing the underlying data
access technology. Theres a small exception to this rule when it comes down to configuring Dependency Injection
which Ill point out in Part 6.
Introduction
In the preceding articles in this series, youve seen how to build the foundation of a data driven application. You saw
how to setup the application, enable it for unit and integration testing, and how to design and build a rich object model
that supports hierarchies, collections and object comparison that can easily be extended with validation. In this article
you will see how to build a data access layer that can persist the objects in the model in a SQL Server database and
how to query and retrieve your objects from that same database. As mentioned in the introduction of this article
series, Ill be using Entity Framework 5 Code First, Microsofts ORM framework to work with POCO (Plain Old CLR
Objects) classes. A lot has already been written on the Entity Framework, so this article wont be an introduction to EF
or EF Code First. If youre new to EF, youre encouraged to check out the following resources:
Programming Entity Framework (Julie Lerman, 2010, http://www.amazon.com/Programming-Entity-
Framework-Building-Centric/dp/0596807260/)
Programming Entity Framework: Code First (Julie Lerman and Rowan Miller, 2011, http://www.amazon.com
/Programming-Entity-Framework-Code-First/dp/1449312942/)
Programming Entity Framework: DbContext (2012, Julia Lerman and Rowan Miller, http://www.amazon.com
/Programming-Entity-Framework-Julia-Lerman/dp/1449312969/)
This article focuses on implementing EF in a reusable and easy configurable way for your N-Layered applications. Itll
cover a number of topics, including:
Adding EF to your project using NuGet.
Building the DbContext class that provides access to the data in the EF model.
Building a context storage mechanism that defines the life span of the DbContext.
Configuring your models business rules (i.e. validation).
Dealing with database initialization.
Implementing a base repository class to implement common queries.
Implementing a concrete repository to manage contact people in the system.
Implementing a Unit of Work.
Managing relationships.
Implementing IDateTracking.
Improving error messages generated by the DbContext.
In the following sections youll see how to implement this functionality in the
Spaanjaars.ContactManager45.Repositories.EF project. First, Ill show you how to enable EF in the project and
create a simple class that inherits DbContext that exposes properties of type DbSet<T> for querying access. Youll also
see a way to centralize the storage of the DbContext so you can use an instance of it per web request.
The next step in the process is to set up the business rules. You see how to use the contexts OnModelCreating
method and special EntityTypeConfiguration classes to define your rules such as whether or not a field is required,
the names of columns and tables in the database, the length of fields and so on. Youll also see how to define an
initialization strategy that defines how the initial database is created, and whether or not it can be recreated
automatically.
A large part of the article is then spent on building repositories. You will see how to build a generic repository that can
serve as the base class for other concrete repositories. You will also see how to create the PeopleRepository and how
to write integration tests to make sure they work correctly. Finally, at the end of the article you will see how to
implement the automatic tracking of the creation and modification dates using the IDateTracking interface and how
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 63 of 162
to improve the error messages that are returned from the DbContext.
The final result is a data access layer that is ready to be used in your UI and other project as youll see in later articles
in this series.
Adding EF to Your Project using NuGet
The first step in building the data access layer is to enable Entity Framework 5 Code First in the project
Spaanjaars.ContactManager45.Repositories.EF. Once again, this is easy to do using NuGet. Open up the Package
Manager Console in Visual Studio 2012 (choose Tools | Library Package Manager | Package Manager Console) and
select the project Spaanjaars.ContactManager45.Repositories.EF in the Default project drop-down list. Then enter
the following command and hit enter:
After a short time, you should see that EF is added to the project correctly:
(2) See Links in this Document at the end for the full URL of this image.
Figure 5-1 Installing EF Using the Package Manager Console
To enable integration tests that target the DbContext, you also need to install Entity Framework in the
Spaanjaars.ContactManager45.Tests.Integration project. To add EF, switch back to the Package Manager Console,
choose Spaanjaars.ContactManager45.Tests.Integration from the Default project drop-down, press the Up arrow
to add the last executed command back on the command line and hit enter. This executes the Install-Package
command again and installs EF in the test project.
With the projects prepared, its now time to add the DbContext class to the project.
Building the DbContext
When using Entity Framework 5 Code First, the core object you interact with is the DbContext, a class designed to
query the underlying database and to group together changes that are written back to the data store in a single unit.
To work with DbContext, you create a class that inherits from this class, and then for each aggregate root you add a
property of type DbSet<T>.
In Domain-driven Design: Tackling Complexity in the Heart of Software, Eric Evans described an aggregate root as
follows:
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each
AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single,
specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are
allowed to hold references to, although objects within the boundaries may hold references to each other.
For the ContactManager application that would mean only Person is an aggregate root, and contact details such as
e-mail addresses and phone numbers are retrieved through the Person. If the application was bigger and had more
aggregate roots, I would create separate DbSet<T> properties (and later on, repositories) for those as well.
In its most simple form, an implementation of DbContext for the Contact Manager application could look like this:
1 Install-Package EntityFramework
1
2
3
namespace Spaanjaars.ContactManager45.Repositories.EF
{
public class ContactManagerContext : DbContext
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 64 of 162
However, with this code, the database that is generated is named after the full type of the DbContext, including its
long namespace. I prefer a shorter name with just the context name, which you can accomplish by adding a
parameterless constructor that calls the base constructor and passes in the desired name:
This is the minimum amount of code you need to interact with contact people in the database. However, as youll see
later, its common to add more code to the DbContext class to configure business rules and intercept the saving
process.
Now that the class is ready, I could write a quick unit test in the Integration Tests project to confirm that everything
works as expected. Heres an example:
Helpers.CreateAddress is a simple helper method that creates and returns a populated Address instance.
Note that I havent specified a connection string anywhere. By default EF uses SQL Express if it is installed. Otherwise,
it will use the new Local DB version that gets installed with VS 2012. After I ran the test, I ended up with a database
called ContactManagerContext that contains a few tables. The People table had the person row inserted by the unit
test:
4
5
6
7
{
public DbSet<Person> People { get; set; }
}
}
1
2
3
4
5
6
7
8
namespace Spaanjaars.ContactManager45.Repositories.EF
{
public class ContactManagerContext : DbContext
{
public ContactManagerContext() : base("ContactManagerContext") { }
public DbSet<Person> People { get; set; }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Model;
using Spaanjaars.ContactManager45.Repositories.EF;

namespace Spaanjaars.ContactManager45.Tests.Integration
{
[TestClass]
public class ContactManagerContextTests
{
[TestMethod]
public void CanAddPersonUsingContactManagerContext()
{
var person = new Person {FirstName = "Imar", LastName = "Spaanjaars",
DateOfBirth = new DateTime(1971, 8, 9), DateCreated = DateTime.Now,
DateModified = DateTime.Now, Type = PersonType.Colleague,
HomeAddress = Helpers.CreateAddress(),
WorkAddress = Helpers.CreateAddress()};
var context = new ContactManagerContext();
context.People.Add(person);
context.SaveChanges();
}
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 65 of 162
(3) See Links in this Document at the end for the full URL of this image.
Figure 5-2 The Generated Database with the People Table
This test uses the ContactManagerContext class directly. The code first creates a new instance of this class, accesses
its People property (that I defined in the code earlier), adds a new person and finally calls SaveChanges to submit the
changes to the underlying SQL Server database. As mentioned earlier, EF uses SQL Express by default if you have it
installed locally. Otherwise, it uses Local DB instead. Check out the following post to learn more about configuring the
database created and used by EF:
http://msdn.microsoft.com/en-us/data/jj556606.aspx
As you learned earlier, this design uses repositories to encapsulate all data access. This means that external code -
such as code in the Presentation layers - shouldnt create or access the ContactManagerContext directly. Instead,
ContactManagerContext should be wrapped by the various repositories. In addition, to implement a unit of work (that
enables you to make multiple changes to your data and submit them to the database all at once), the repositories
shouldnt create instances of ContactManagerContext themselves in each public method. Instead, it would be useful
to have a centralized context factory class that can create instances for you. The sole purpose of that class would be to
create instances of another class; hence the name factory. For more information on the factory design pattern, take a
look at this article: http://www.oodesign.com/factory-pattern.html.
Additionally, it would be very useful if the same ContactManagerContext instance was used for the entire HTTP
request. This way, you can share the same instance across multiple pieces of code running in the same request,
minimizing the overhead needed to create new instances and giving you the opportunity to treat multiple database
updates as a single unit. You see how this works next.
Building a Context Storage Mechanism
Note: the following section and code is based directly on the work by Scott Millett. I first saw this in his book
Professional ASP.NET Design Patterns (Wrox, 2010, http://www.amazon.com/Professional-ASP-NET-Design-Patterns-
Millett/dp/0470292784). I modified Scotts example and made most classes generic so they can store any type of
object, but other than that, the core concepts are the same.
To implement a factory class that can create and return instances of ContactManagerContext and store them in an
appropriate location, the sample project contains the following five types:
Type Name Description
DataContextFactory A static class with a static GetDataContext method that returns an instance of
the ContactManagerContext class. Under the hood, it creates an instance of a
class that inherits IDataContextStorageContainer to store the data context
so its accessible for multiple calls. You see how this works shortly.
DataContextStorageFactory A static class with a static CreateStorageContainer method that returns an
instance of a class that inherits IDataContextStorageContainer that is used
to store the ContactManagerContext. When HttpContext is available, the
instance returned is HttpDataContextStorageContainer that stores the data
context in the HttpContext.Curent.Items collection. Otherwise, the method
returns an instance of ThreadDataContextStorageContainer that stores the
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 66 of 162
data context in the current threads Items collection.
IDataContextStorageContainer An interface with methods to return, create and clear a data context.
HttpDataContextStorageContainer A concrete implementation of IDataContextStorageContainer which stores
the data context in the HttpContext. This version is used in all web-related
projects.
ThreadDataContextStorageContainerA concrete implementation of IDataContextStorageContainer which stores
the data context in the current thread. This version is used in desktop
applications and in unit test projects.
The following figure shows these five types and their members:
(4) See Links in this Document at the end for the full URL of this image.
Figure 5-3 The Class Diagram for the Data Context Storage Classes
I added DataContextFactory to the Repositories.EF project as it contains references to the actual data context
class which is specific to the ContactManager application. The other four are not tied to any concrete implementation
and are thus added to the Infrastructure project. This makes them easy to reuse across your projects.
To implement this factory, I created a new folder called DataContextStorage to the Spaanjaars.Infrastructure
project. I then added a new interface file, called IDataContextStorageContainer and added the following code:
This interface defines the contract to get, store and clear the ContactManagerContext. Next, I added two classes,
called HttpDataContextStorageContainer and ThreadDataContextStorageContainer and added the following code:
1
2
3
4
5
6
7
8
9
namespace Spaanjaars.ContactManager45.Repositories.EF
{
public interface IDataContextStorageContainer<T>
{
T GetDataContext();
void Store(T objectContext);
void Clear();
}
}
1
2
3
using System.Web;

namespace Spaanjaars.Infrastructure.DataContextStorage
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 67 of 162
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
public class HttpDataContextStorageContainer<T> :
IDataContextStorageContainer<T> where T : class
{
private const string DataContextKey = "DataContext";

public T GetDataContext()
{
T objectContext = null;
if (HttpContext.Current.Items.Contains(DataContextKey))
{
objectContext = (T)HttpContext.Current.Items[DataContextKey];
}
return objectContext;
}

public void Clear()
{
if (HttpContext.Current.Items.Contains(DataContextKey))
{
HttpContext.Current.Items[DataContextKey] = null;
}
}

public void Store(T objectContext)
{
if (HttpContext.Current.Items.Contains(DataContextKey))
{
HttpContext.Current.Items[DataContextKey] = objectContext;
}
else
{
HttpContext.Current.Items.Add(DataContextKey, objectContext);
}
}
}
}

using System;
using System.Collections;
using System.Threading;
namespace Spaanjaars.Infrastructure.DataContextStorage
{
public class ThreadDataContextStorageContainer<T> :
IDataContextStorageContainer<T> where T : class
{
private static readonly Hashtable StoredContexts = new Hashtable();

public T GetDataContext()
{
T context = null;

if (StoredContexts.Contains(GetThreadName()))
{
context = (T)StoredContexts[GetThreadName()];
}
return context;
}

public void Clear()
{
if (StoredContexts.Contains(GetThreadName()))
{
StoredContexts[GetThreadName()] = null;
}
}

public void Store(T objectContext)
{
if (StoredContexts.Contains(GetThreadName()))
{
StoredContexts[GetThreadName()] = objectContext;
}
else
{
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 68 of 162
Both classes solve the same problem: they enable you to store, clear and retrieve an instance of a class. In the sample
application, this class is a ContactManagerContext but you could also use this code to work with other data types. The
HTTP version stores its data in the Items collection of the HttpContext, while the thread version stores the object in a
static collection indexed by the threads name. The Clear method is primarily used for unit test scenarios so you can
force a clean context on every test, rather than storing a single context for the life time of the thread that runs the
unit tests. You see how this works later in this article.
The final class in the Spaanjaars.Infrastructure project is DataContextStorageFactory and its code looks like this:
This static class has a single method called CreateStorageContainer that returns an instance of one of the two
storage containers you saw earlier. The method checks whether or not HttpContext is null or not. When its not
(which should be the case in web applications such as a Web Forms or an MVC application), it returns a new
HttpDataContextStorageContainer. Otherwise, it returns a new ThreadDataContextStorageContainer. Whats cool
about this method and the way it is implemented is that it runs anywhere, and does the right thing based on the
context. If you run this in a web application, the data context is stored in HttpContext. This means that its available
throughout a single request; whether thats in an MVC controller, an ASPX page, or a user control; as long as they all
execute in the same HttpContext, they use the same data context.
With this code in the Infrastructure project, the implementation in the Repositories.EF project is now pretty
simple. All you need is this class:
79
80
81
82
83
84
85
86
87
88
89
90
91
92
StoredContexts.Add(GetThreadName(), objectContext);
}
}

private static string GetThreadName()
{
if (string.IsNullOrEmpty(Thread.CurrentThread.Name))
{
Thread.CurrentThread.Name = Guid.NewGuid().ToString();
}
return Thread.CurrentThread.Name;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System.Web;

namespace Spaanjaars.Infrastructure.DataContextStorage
{
public static class DataContextStorageFactory<T> where T : class
{
private static IDataContextStorageContainer<T> _dataContextStorageContainer;

public static IDataContextStorageContainer<T> CreateStorageContainer()
{
if (_dataContextStorageContainer == null)
{
if (HttpContext.Current == null)
{
_dataContextStorageContainer = new ThreadDataContextStorageContainer<T>();
}
else
{
_dataContextStorageContainer = new HttpDataContextStorageContainer<T>();
}
}
return _dataContextStorageContainer;
}
}
}
1
2
3
4
5
6
using Spaanjaars.Infrastructure.DataContextStorage;

namespace Spaanjaars.ContactManager45.Repositories.EF
{
public static class DataContextFactory
{
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 69 of 162
The GetDataContext method retrieves an instance of an IDataContextStorageContainer from the
DataContextStorageFactory class. It then checks if it already contains a ContactManagerContext. If that isnt the
case, a new instance is created and stored in the container using the Store method. At the end the method returns
the ContactManagerContext instance.
The Clear method uses the same code to retrieve a container and then calls Clear to clear the DbContext from
HttpContext or from the current thread, depending on the type of the container.
Although this seems like a lot of work, I find it worthwhile to implement it like this. First of all, most of the code is in
the shared Infrastructure project so you need to only write this once. Secondly, once this is setup, using the data
context is now super easy. Whenever you need an instance of the ContactManagerContext, all you need to do is call
this:
So, for example, if you want to retrieve contact people from the database and use the EF Data Context, you can
execute a query like this:
A more complete example can be found in the ContactManagerContextTests class in the Integration test project:
To close off the discussion on the context storage mechanism, heres a run-down of the process that takes place when
you call DataContextFactory.GetDataContext():
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static void Clear()
{
var dataContextStorageContainer =
DataContextStorageFactory<ContactManagerContext>.CreateStorageContainer();
dataContextStorageContainer.Clear();
}

public static ContactManagerContext GetDataContext()
{
var dataContextStorageContainer =
DataContextStorageFactory<ContactManagerContext>.CreateStorageContainer();
var contactManagerContext = dataContextStorageContainer.GetDataContext();
if (contactManagerContext == null)
{
contactManagerContext = new ContactManagerContext();
dataContextStorageContainer.Store(contactManagerContext);
}
return contactManagerContext;
}
}
}
1 DataContextFactory.GetDataContext()
1 var people = DataContextFactory.GetDataContext().People.Where(x => x.LastName == lastName);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TestMethod]
public void CanExecuteQueryAgainstDataContext()
{
string lastName = Guid.NewGuid().ToString();
var context = DataContextFactory.GetDataContext();
var person = new Person
{
FirstName = "Imar", LastName = lastName,
DateOfBirth = new DateTime(1971, 8, 9), DateCreated = DateTime.Now,
DateModified = DateTime.Now, Type = PersonType.Colleague,
HomeAddress = Helpers.CreateAddress(),
WorkAddress = Helpers.CreateAddress()
};
context.People.Add(person);
context.SaveChanges();
var personCheck = context.People.Single(x => x.LastName == lastName);
personCheck.Should().NotBeNull();
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 70 of 162
This method first creates a new storage container by calling
DataContextStorageFactory<ContactManagerContext>.CreateStorageContainer(). In a web project, this
code returns an HttpDataContextStorageContainer and in unit tests (or other applications where
HttpContext is not available), it returns a ThreadDataContextStorageContainer.
It then calls GetDataContext on the container. That method checks its underlying storage mechanism to see if
an instance of the ContactManagerContext exists and then returns it, or it returns null.
When the ContactManagerContext is null, a new instance is created and then stored by calling Store on the
container. Again, the respective context containers use their underlying storage mechanism to store the
ContactManagerContext.
Finally, the ContactManagerContext is returned to the calling code.
Youll see more concrete examples of GetDataContext in this and later articles.
Back in Part 4, I said you needed a DbContext to set up business rules using the API. Now that the data context is
done, its time to look at that in more detail.
Configuring your Models Business Rules
Entity Framework has great support for validation built in. When you add an object to the context or edit an existing
one and then try to save the changes, EF ensures the object is in a valid state. If its not valid, an exception is thrown,
and the entity is not saved in the database. The validation mechanism that EF supports enable you to implement both
property level validation (to validate things like a required field, a maximum length and so on) as well as object level
validation (for example, to compare two fields with each other, or use other business logic to determine validity.) The
next sections dig deeper into these topics.
Implementing Property Level Validation Using Attributes
Property level validation is probably the easiest concept to grasp. A property is either valid or its not. What makes it
valid or invalid depends on the rules you write for it. To do this, you have two options: attributes and the fluent API.
When you use the attribute approach, you use attributes from the System.ComponentModel.DataAnnotations
namespace and place them on a property. The following example shows a FirstName property that is required (cannot
be null or an empty string) and that has a maximum length of 25 characters.
Likewise, if you wanted to ensure an integer value falls between a certain range, you can use the Range attribute as
follows:
More information about the various attributes can be found at the following pages:
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
http://www.dotnetattributes.com/System/ComponentModel/DataAnnotations
http://msdn.microsoft.com/en-us/data/jj591583.aspx
While the attribute-based approach works fine (and is very similar to what I used in the previous version of my layered
design), EF offers a cleaner way to do this: by configuring your entities on the DbContext class.
NOTE: youll see a mix of both solutions in the sample project. I have added a few simple Required attributes to the
entities in the Model project for properties I really want to be required such as names of a person and the text of an
e-mail address. This in turn enables me to write some quick unit tests to make validation works correctly. If you dont
like this because it pollutes the model, simply remove the attributes and replace them with the fluent API methods as
youll see shortly. This will break some of the unit tests so you need to either remove them from the project or rewrite
them as integration tests using an Entity Framework context.
Implementing Property Level Validation using the Fluent API
When EF initializes its model the first time, it fires a method called OnModelCreating on the DbContext class. This is
the place where you can write your business rules for your entities. As a parameter, the method accepts an instance of
a DbModelBuilder class that in turn has a generic Entity method (among other members) that lets you specify your
1
2
[Required, MaxLength(25)]
public string FirstName { get; set; }
1
2
[Range(0,130)]
public int Age { get; set; }
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 71 of 162
rules. The following code is equivalent to the previous sample that used a Required and a MaxLength attribute.
Notice how the configuration code uses a lambda expression to specify the FirstName property. It can access this
property because the Entity method has a type argument of type Person. Once you have a reference to a property,
you can call methods like IsRequired and HasMaxLength. Notice how this is a fluent API, where each call returns an
object on which other methods can be called.
The Entity method has more members that let you specify the table name (ToTable), specify keys (HasKey) and
configure relationships (HasMany, HasOptional and HasRequired). You see some of these at work later, but for an
in-depth look at configuring EF using the Fluent API, check out:
Programming Entity Framework: Code First, Julia Lerman, 2011 (http://www.amazon.com/Programming-Entity-
Framework-Code-First/dp/1449312942/)
If you have many entities in your model with many rules per entity, the OnModelCreating method may become
unwieldy pretty quickly. While you could move some code to separate methods, EF has a better alternative: the
EntityTypeConfiguration class.
The EntityTypeConfiguration class is designed to configure your EF entities using the Fluent API. To use it, you
create a class that inherits from it and specify an entity in its generic type parameter. This way, each
EntityTypeConfiguration is for a specific entity. Once you create that class, you can specify all the configuration
code in its constructor. Finally, you need to add an instance of this class to the ModelBuilders Configurations
property. You see how to implement each of these steps next.
To configure the Person class, I created a new class called PersonConfiguration in the Configuration folder of the
Repositories.EF project. I then added the following code:
Notice how the class inherits from EntityTypeConfiguration<Person> to make it strongly typed for the Person class.
This then enables you to write your configuration code in the constructor like this:
This code is very similar to the previous example directly in the OnModelCreating method. However, its now much
easier to see how an entity is configured: just look at its associated EntityTypeConfiguration class. Youre not
limited to configuring properties. Just like the ModelBuilder, you can configure things like the table name,
relationships, data types, column names, and more.
To add the configuration class to the model, you use the same OnModelCreating override in the
ContactManagerContext class but now add an instance of EntityTypeConfiguration to the Configurations
collection:
1 modelBuilder.Entity<Person>().Property(x => x.FirstName).IsRequired().HasMaxLength(25);
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Data.Entity.ModelConfiguration;
using Spaanjaars.ContactManager45.Model;

namespace Spaanjaars.ContactManager45.Repositories.EF.Configuration
{
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
//Todo Configure business rules here
}
}
}
1
2
3
4
public PersonConfiguration()
{
Property(x => x.FirstName).IsRequired().HasMaxLength(25);
}
1
2
3
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new PersonConfiguration());
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 72 of 162
In this example, only one config class is added, but you can add more by calling Add multiple times, each time passing
in an instance for a different entity type. In the sample code you see classes being added for Person, EmailAddress
and PhoneNumber.
The EntityTypeConfiguration class for Person in the sample application also contains code to rename the columns
for the home and work addresses. The default of EF is to name the columns of complex types after the main property
name and its own sub properties, each separated by an underscore. This would result in properties like
WorkAddress_Street in the People table. I dont like the underscores, so I specified the new column names like this:
NOTE: setting column names isnt about validation, but rather configuration of your application and database.
However, since EF uses the same mechanism to do both, I decided to discuss it in this section.
While property level validation gets you a long way in specifying your business rules, you typically have validation rules
that cant be expressed with property level validation. For example, what if you want to compare two properties with
each other? This is useful if you want to ensure that, say, an EndDate is greater than a StartDate (unless youre
modelling software for a time travel machine of course). Likewise, you may want to reject a date that is outside an
allowed range, or you may want to make certain members of an enumeration invalid options. So how do you
implement these business rules? Enter object level validation.
Implementing Object Level Validation
In the previous version of my N-Layer design article series object level validation was implemented in the
ValidationBase class with the Validate method that returned a list of broken rules. This method would still work in
the new design. However, theres now a much better solution for this. In the
System.ComponentModel.DataAnnotations namespace theres an interface called IValidatableObject. It has a
single method called Validate that returns an IEnumerable<ValidationResult>. Inside this method, you can
validate your object and then return any validation error you may detect.
The cool thing about this solution is that other areas of the .NET Framework such as Entity Framework and ASP.NET
MVC are aware of this interface too. This means that if you implement this interface in your objects, they automatically
benefit from the validation features these .NET features have to offer. For EF, it means Validate is called before an
attempt is made to save the object in the database. In ASP.NET MVC, this interface helps drive the model validation
features.
So, it sounds like IValidatableObject is the way to go, and I think it really is. To make sure all my entities support it,
I added the IValidatableObject interface to the DomainEntity<T> and ValueObject<T> classes and implemented
the required Validate method as abstract so inheriting types are forced to write an implementation for it. Heres the
relevant code from DomainEntity<T>:
Theres only one minor problem with the Validate method on this interface: it expects an instance of
ValidationContext which is used to determine the context in which validation takes place. EF and MVC automatically
pass in this context, but for your own code its a bit awkward. Fortunately, its easy to create a parameterless overload
of Validate that calls the other version and passes in a reference to itself (the entity being validated). To make the
method available to all domain entities, I added it to the DomainEntity and ValueObject classes in the
Spaanjaars.Infrastructure project like this:
4 }
1
2
3
4
5
Property(x => x.WorkAddress.Street).HasColumnName("WorkAddressStreet").HasMaxLength(50);
Property(x => x.WorkAddress.City).HasColumnName("WorkAddressCity").HasMaxLength(50);
Property(x => x.WorkAddress.ZipCode).HasColumnName("WorkAddressZipCode").HasMaxLength(15);
Property(x => x.WorkAddress.Country).HasColumnName("WorkAddressCountry").HasMaxLength(30);
Property(x => x.WorkAddress.ContactType).HasColumnName("WorkAddressContactType");
1
2
3
4
5
6
public abstract class DomainEntity<T> : IValidatableObject
{
...
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
...
}
1
2
public IEnumerable<ValidationResult> Validate()
{
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 73 of 162
Whenever this method is called on an instance of your object it eventually also calls the version that expects a
ValidationContext. That method is the place where you need to write your own validation code, if any. Heres an
example from the Person class:
Notice how the method needs to return an IEnumerable<ValidationResult>. In C# (and since .NET 4.5 also in
VB.NET) you can use the yield return keywords to return a new ValidationResult for each error in your model.
Calling code can then simply use a foreach loop to access all the errors. If you dont have the need to implement
validation in one or more of your entities, simply return yield break, like this:
Since the Validate method is called for the entire instance, its now easy to implement object level validation with
dynamic rules. For example, take a look at how Person makes sure the DateOfBirth is smaller than today:
3
4
5
6
7
var validationErrors = new List<ValidationResult>();
var ctx = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, ctx, validationErrors, true);
return validationErrors;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Type == PersonType.None)
{
yield return new ValidationResult("Type can't be None.", new[] { "Type" });
}

if (DateOfBirth < DateTime.Now.AddYears(Constants.MaxAgePerson * -1))
{
yield return new ValidationResult("Invalid range for
DateOfBirth; must be between today and 130 years ago.", new[] { "DateOfBirth" });
}

if (DateOfBirth > DateTime.Now)
{
yield return new ValidationResult("Invalid range for
DateOfBirth; must be between today and 130 years ago.", new[] { "DateOfBirth" });
}

foreach (var result in PhoneNumbers.Validate())
{
yield return result;
}

foreach (var result in EmailAddresses.Validate())
{
yield return result;
}

foreach (var result in HomeAddress.Validate())
{
yield return result;
}

foreach (var result in WorkAddress.Validate())
{
yield return result;
}
}
1
2
3
4
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
yield break;
}
1
2
3
4
if (DateOfBirth > DateTime.Now)
{
yield return new ValidationResult(
"Invalid value for DateOfBirth; must between today and 130 years ago.", new [] { "DateOfBirth" });
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 74 of 162
You wouldnt be able to do this using attributes alone as the validation rules can only express constant values, and not
something as dynamic as the current date.
Note how I am also calling Validate on the two addresses and the two contact data collections. Inside the
EmailAddresses and PhoneNumbers classes you find code like this:
This code loops over the collection of addresses (using the this reference) and then calls Validate on each individual
instance, storing the result in a temporary list which is returned at the end. If you dont feel like duplicating this code
in each collection you could create a class called ValidatableCollectionBase that in turn inherits CollectionBase.
You can then implement the behavior there once, and let PhoneNumbers and EmailAddresses inherit this new
collection.
Its important to realize that your custom Validate method is not called as long as one of the Required or other
validation attributes or property-based rules set using thee Fluent API are causing the object to be invalid. So for
instance with this code:
the brokenRules collection will only contain two ValidationResult instances for FirstName and LastName (both are
required), and not for the DateOfBirth. Once you assign FirstName and LastName a value, then the custom Validate
method is called and the DateOfBirth is rejected:
The Validation method of Address looks a bit different. Its a ComplexType which cant be null by itself, and
therefore nullability is determined by looking at all the individual properties using IsNull:
5 }
1
2
3
4
5
6
7
8
9
public IEnumerable<ValidationResult> Validate()
{
var errors = new List<ValidationResult>();
foreach (var number in this)
{
errors.AddRange(number.Validate());
}
return errors;
}
1
2
Person person = new Person { DateOfBirth = DateTime.Now.AddDays(10) };
var brokenRules = person.Validate();
1
2
3
Person person = new Person { FirstName = "Imar", LastName = "Spaanjaars",
DateOfBirth = DateTime.Now.AddDays(10) };
var brokenRules = person.Validate(); // Now contains two results, for Type and for DateOfBirth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public bool IsNull
{
get
{
return (string.IsNullOrEmpty(Street) && string.IsNullOrEmpty(ZipCode) &&
string.IsNullOrEmpty(City) && string.IsNullOrEmpty(Country));
}
}

public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!IsNull)
{
if (ContactType == ContactType.None)
{
yield return new ValidationResult("ContactType can't be None.", new[] { "ContactType" });
}
if (string.IsNullOrEmpty(Street))
{
yield return new ValidationResult("Street can't be null or empty", new[] { "Street" });
}
if (string.IsNullOrEmpty(ZipCode))
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 75 of 162
When all properties are null, the class is considered valid (that is, its interpreted as no address is supplied which is a
valid situation for this application). However, if at least one property has a value, all of them must have a value. For
more information on complex types and nullability, check out this blog:
http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-
one-associations.aspx
Also note that I havent written code to validate zip codes or addresses. However, its relatively simple to implement
this. Youll find many regular expressions on-line for zip codes which you could combine with the selected country.
With the validation implemented, I could now update my test projects and add a bunch of tests to test the validation in
the various entities. For example, here are a few tests from the PersonTests class in the Unit Tests project:
The CreatePerson method is a simple helper method that returns an instance of a Person:
Dealing with Database Initialization
During initial development of the application its common that your model changes quite a bit between runs of your
application and integration tests. That means that at some point youll run into this error:
23
24
25
26
27
28
29
30
31
32
33
34
35
{
yield return new ValidationResult("ZipCode can't be null or empty", new[] { "ZipCode" });
}
if (string.IsNullOrEmpty(City))
{
yield return new ValidationResult("City can't be null or empty", new[] { "City" });
}
if (string.IsNullOrEmpty(Country))
{
yield return new ValidationResult("Country can't be null or empty", new[] { "Country" });
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[TestMethod]
public void FirstNameIsRequired()
{
Person person = new Person();
person.Validate().Count(x => x.MemberNames.Contains("FirstName")).Should().BeGreaterThan(0);
}

[TestMethod]
public void LastNameIsRequired()
{
Person person = new Person();
person.Validate().Count(x => x.MemberNames.Contains("LastName")).Should().BeGreaterThan(0);
}

[TestMethod]
public void PersonWithTypeNoneIsInvalid()
{
Person person = CreatePerson();
person.Type = PersonType.None;
person.Validate().Count(x => x.MemberNames.Contains("Type")).Should().BeGreaterThan(0);
}
1
2
3
4
5
public static Person CreatePerson()
{
return new Person { FirstName = "Imar", LastName = "Spaanjaars",
Type = PersonType.Friend, DateOfBirth = DateTime.Now.AddYears(-20) };
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 76 of 162
(5) See Links in this Document at the end for the full URL of this image.
Figure 5-4 Error Running a Unit Test
The error message says that the model has changed and is no longer in sync with the database. There are a couple of
ways to solve this problem:
Using Database Initializers like DropCreateDatabaseIfModelChanges and DropCreateDatabaseAlways. These
initializers will drop the database and then recreate it. The first one does this only when the model has changed
while the second one will do it every time the object context is instantiated for the first time within an
application domain.
Using EF Migrations. With Migrations you can script the differences between model versions and use that
information to update the target database through code or SQL statements.
Manually update the production database with SQL Scripts that you can generate by comparing the production
database with the development database. Tools like Red Gates SQL Compare come in really handy here. You'll
find more information about this tool in Part 10.
Ive used Migrations in a couple of my projects and it works well. However, I dont always find it a good solution to
update the database at runtime for production environments as the account used to access the database then also
needs DDL permissions. So, instead I use a combination of option 1 and 3 like this:
I am using a specialized version of DropCreateDatabaseIfModelChanges at development time. Using this
class, I can drop and recreate the database when needed. Using an override of Seed, I can also insert some
default data that I might need for my integration tests or create additional database objects such as indexes on
tables.
At production time, I turn of the database initializer. This means the model is not checked when the application
starts up. This in turn means you may end up with errors when a column or table isnt found; a column is now
required or when the data type for the column has changed. However, using diff scripts you can quickly bring
the production database in sync, so I am typically willing to take this risk.
I add a static class (called ContactManagerContextInitializer in the sample application) to my EF Project
that has an Init method that sets a database initializer, or turns it off. The code in the Repositories.EF
project looks like this:
Based on the value of dropDatabaseIfModelChanges, this code either sets the initializer to
MyDropCreateDatabaseIfModelChanges or it turns it off by passing null. In the second case, the database is not
checked for compatibility with the model and its up to you to make sure the database is up to date. You can override
the Seed method of the MyDropCreateDatabaseIfModelChanges class and insert default records like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static class ContactManagerContextInitializer
{
public static void Init(bool dropDatabaseIfModelChanges)
{
if (dropDatabaseIfModelChanges)
{
Database.SetInitializer(new MyDropCreateDatabaseIfModelChanges());
using (var db = new ContactManagerContext())
{
db.Database.Initialize(false);
}
}
else
{
Database.SetInitializer<ContactManagerContext>(null);
}
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 77 of 162
This way you have default data present in the database that you might need for other integration tests. In the Contact
Manager application no data is needed, but this could be useful for scenarios where you want to prefill some lookup
tables like countries or states for example.
From the integration tests project in the Contact Manager application, I call the Init method like this (in the
constructor of IntegrationTestBase that all my integration test classes inherit from):
In my production applications, such as the MVC project, I could call Init like this (for example, in Global.asax):
However, this makes it a bit hard to test the presentation projects during development because you then often do want
the database to be generated automatically for you so its up to date. Fortunately, EF lets you enable or disable the
database initializers through the web.config as well. This in turn means its easy to have different settings in
development, production and other environments by using Web.config Transformations. My web.config for production
could look like this:
This disables the database initialization completely; leaving it up to you to make sure the database is in a valid state.
At development time, I could use this configuration code instead:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyDropCreateDatabaseIfModelChanges :
DropCreateDatabaseIfModelChanges<ContactManagerContext>
{
protected override void Seed(ContactManagerContext context)
{
var person = new Person
{
FirstName = "Imar",
LastName = "Spaanjaars",
DateOfBirth = new DateTime(1971, 8, 9),
Type = PersonType.Friend
};
person.HomeAddress = CreateAddress();
person.WorkAddress = CreateAddress();
context.People.Add(person);
}

private static Address CreateAddress()
{
return new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
}
}
1
2
3
4
5
6
7
public class IntegrationTestBase
{
public IntegrationTestBase()
{
ContactManagerContextInitializer.Init(true);
}
}
1
2
3
4
5
6
protected void Application_Start()
{
...
ContactManagerContextInitializer.Init(false);
...
}
1
2
3
4
5
6
<entityFramework>
<contexts>
<context type="Spaanjaars.ContactManager45.Repositories.EF.ContactManagerContext,
Spaanjaars.ContactManager45.Repositories.EF" disableDatabaseInitialization="true" />
</contexts>
</entityFramework>
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 78 of 162
This configures the MyDropCreateDatabaseIfModelChanges to be used as the database initializer during development,
which is very helpful as I get a new database automatically whenever the model has changed.
More info on database initializers and web.config transformations can be found here:
http://www.codeguru.com/csharp/article.php/c19999/Understanding-Database-Initializers-in-Entity-
Framework-Code-First.htm
http://msdn.microsoft.com/en-us/data/gg194002.aspx (video)
http://blog.oneunicorn.com/category/entity-framework/database-initializers/
http://msdn.microsoft.com/en-us/library/dd465318%28v=vs.100%29.aspx
http://www.codeproject.com/Tips/559849/Transform-Web-Config-when-Deploying-a-Web-Applicat
http://www.asp.net/web-forms/tutorials/deployment/deployment-to-a-hosting-provider/deployment-
to-a-hosting-provider-web-config-file-transformations-3-of-12
Implementing a Base Repository Class to Centralize Common
Queries
At this point, a lot of the plumbing for the application has been done. To recap and see where we are, heres the
current state of the application:
A new model has been created that contains the applications core entities.
Theres an Infrastructure project that contains base types for your entities and other objects.
The model implements property and object level validation, using attributes from the DataAnnotations
namespace and the fluent EF API.
Theres a DbContext class with a property called People that can be used by calling code to query the
underlying database.
There are unit and integration tests to make sure everything works as expected.
With this setup, you could now start to create instances of ContactManagerContext directly and query the People
collection to get at the data in your database and create new entities. However, this isnt recommended because itll
make your code harder to reuse and test. Suppose you have some code in an MVC Controller or the Code Behind of a
Web Form that retrieves a Person from the database by its ID. This is very common code and its likely youll need this
code more often. Without a way to centralize this behavior, youll be copying and pasting your code all over the place,
making your application harder to understand and maintain. In addition, your code is now tied to a concrete instance
of the ContactManagerContext (which in turns is tightly coupled to the database), making it much harder to unit test
your controllers.
As a solution to this problem, you should create a Repository. Under Martin Fowlers definition, a repository mediates
between the domain and data mapping layers using a collection-like interface for accessing domain objects.
A Repository enables you to centralize all your data access methods revolving around an entity in a single, centralized
class per entity. Quite often, a repository is based on a generic IRepository<T> interface that in turn implements
members such as FindById (to find an instance based on its unique key in the database), FindAll to get access to all
objects of a specific type, Add (to add new instances to the underlying database) and Remove to delete items from the
database.
Note: the application makes use of the Repository pattern. For alternatives to this pattern, see:
http://lostechies.com/jimmybogard/2012/09/20/limiting-your-abstractions/
http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/
You already saw the design of the generic repository in Part 4, but here's a quick recap. I started implementing the
repository pattern in the ContactManager with the following IRepository interface in the Infrastructure project:
1
2
3
4
5
6
7
8
9
10
<entityFramework>
<contexts>
<context type="Spaanjaars.ContactManager45.Repositories.EF.ContactManagerContext,
Spaanjaars.ContactManager45.Repositories.EF" disableDatabaseInitialization="false">
<databaseInitializer type="
Spaanjaars.ContactManager45.Repositories.EF.MyDropCreateDatabaseIfModelChanges,
Spaanjaars.ContactManager45.Repositories.EF" />
</context>
</contexts>
</entityFramework>
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 79 of 162
Figure 5-5 The IRepository Interface
From a code perspective, the interface looks like this:
The class has two generic type parameters: one for the actual entity (T, which can be a type such as Person) and one
for its key type (K, which is always an int in the Contact Manager Application but it could be something else like a
Guid).
The interface definition uses a where clause to limit the type of T to a DomainEntity<T> so you cant accidentally
create a repository on an unrelated type. In addition, within the Repository you then know the base class of the type
youre dealing with which you can use in methods like FindById as youll see later.
Most of this should look relatively straightforward; FindById expects a K (such as an int, the ID of a Person) and
returns a T (such as a Person). FindAll returns an IQueryable<T> which means your code can further query the
resulting set of objects. Add and Remove each expect a T that is added to or removed from the database, respectively.
Remove also has a convenient overload that expects just the ID of the entity you want to remove, making it easier to
delete an object for which you only have its ID.
Both FindById and FindAll have a funky parameter called includeProperties: a params parameter (which means
you can specify an arbitrary number of values) of type Expression<Func<T, object>>[]. This parameter enables you
to specify the properties you want to include when retrieving an entity from the database. Consider this example:
Depending on how you set things up, this may either result in a lazy loaded call to the database to fetch the e-mail
addresses for this person, or in a null reference exception. To force eager loading, you can specify the properties you
want EF to return when it goes out to the database to fetch the requested Person. With the includeProperties
parameter and some concrete implementation in the Repository base class that youll see shortly, you can now
execute something like this:
The lambda expression in the call to FindById indicates that you want to eager-load the EmailAddresses collection.
This means that when the Person is fetched, all its associated e-mail addresses are fetched as well in the same SQL
call, minimizing execution time and network overhead, thus improving application performance. All other complex
1
2
3
4
5
6
7
8
9
10
public interface IRepository<T, K> where T : class
{
T FindById(K id, params Expression<Func<T, object>>[] includeProperties);
IQueryable<T> FindAll(params Expression<Func<T, object>>[] includeProperties);
IEnumerable<T> FindAll(Expression<Func<T, bool>>
predicate, params Expression<Func<T, object>>[] includeProperties);
void Add(T entity);
void Remove(T entity);
void Remove(K id);
}
1
2
Person person = repository.FindById(123);
string firstEmailAddress = person.EmailAddresses[0].EmailAddressText;
1
2
Person person = repository.FindById(123, p => p.EmailAddresses);
string firstEmailAddress = person.EmailAddresses[0].EmailAddressText;
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 80 of 162
properties that are not specified, such as PhoneNumbers are not fetched. If you want to load multiple properties,
simply provide them in a comma separated list:
With the interface for the repository out of the way, the next step is to implement a repository class based on it. Until
recently, I would create a new Repository class for each of my aggregate roots. The repository classes would then
implement the IRepository interface directly. Something like this would have worked;
This code does a few important things; first, it uses the GetDataContext method to fetch the applications data
context so it can access its People property to get access to that DbSet. It then loops over the properties that need to
be included, calling Include on EFs DbSet. This information eventually gets passed to the database where its used to
query the Person and its related data.
The final line of code queries the requested Person from the database and returns it when it exists. If it doesnt, the
code returns null.
While this code works fine, it gets boring to write after a while. Once you write your second or third repository, youll
notice that most of it is the same, except for the type (Person in this case) of the entity and the collection in the data
context that is being queried (People in this case). If you want to implement a base class repository that other classes
can inherit from and that centralizes the code that is the same for each repository, youll need to overcome these two
differences.
The first issue is simple to solve: simply use generics. Heres a (non-functional) example of how you could implement
this:
Notice how each occurrence of Person has been replaced with T, making the class applicable for any
DomainEntity<T>. Using this base class, you could now create a concrete PersonRepository with only a few lines of
1 Person person = repository.FindById(123, p => p.EmailAddresses, p => p.PhoneNumbers);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class PersonRepository : IRepository<Person, int>
{
public Person FindById(int id,
params Expression<Func<Person, object>>[] includeProperties)
{
IQueryable<Person> people = DataContextFactory.GetDataContext().People;
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties)
{
people = people.Include(includeProperty);
}
}
return people.SingleOrDefault(x => x.Id == id);
}

// Other methods go here
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class Repository<T> : IRepository<T, int> where T : DomainEntity<int>
{
public virtual T FindById(int id, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> items = DataContextFactory.GetDataContext().??????;
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties)
{
items = items.Include(includeProperty);
}
}
return items.SingleOrDefault(x => x.Id == id);
}

// Other code here
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 81 of 162
code:
The only problem that needs to be solved is getting the right collections of items, marked with ?????? in the
highlighted in the code block above. One solution would be to build in a switch statement that would access the proper
collection (e.g. People), based on the type of T. However, that would be a bit lame as a solution and would easily
break as you add new types. After some research, I found out that DbContext (on which ContactManagerContext is
based) has a generic Set method that returns an IQueryable for any given type it supports. This turned out to be the
solution to the problem; I can use this method in my generic repository like this:
Voila: a fully generic, and type safe method that returns an instance of T from the database. I wrote similar code for
the other methods in the repository to implement basic CRUD operations for all core types in the application. Since I
made all methods virtual, they only serve as a base implementation. If you have a reason to write a different
implementation in one of your repositories, simply override the relevant method and change the implementation.
Implementing Search
In Part 4 of this series you saw that the IRepository (and thus the concrete repositories that are based on it) have an
overload of FindAll that accepts a predicate parameter used for searching. In the interface, the method looks like
this:
The concrete implementation looks like this:
Notice how the predicate parameter is forwarded to the Where method that uses it to build up the correct search
expressions. Whats really cool about this is that the search criteria are forwarded to the database, so filtering takes
place at the database level. Consider this concrete example:
1
2
3
public class PeopleRepository : Repository<Person>, IPeopleRepository
{
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Repository<T> : IRepository<T, int> where T : DomainEntity<int>
{
public virtual T FindById(int id, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> items = DataContextFactory.GetDataContext().Set<T>;
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties)
{
items = items.Include(includeProperty);
}
}
return items.SingleOrDefault(x => x.Id == id);
}
// Other code here
}
1
2
IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate,
params Expression<Func<T, object>>[] includeProperties);
1
2
3
4
5
6
7
8
9
10
11
12
13
public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate,
params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> items = DataContextFactory.GetDataContext().Set<T>();
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties)
{
items = items.Include(includeProperty);
}
}
return items.Where(predicate);
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 82 of 162
The SQL code for this LINQ query looks like this:
With this code, the database filters the rows based on the requested values for the first name and the type, resulting
in optimal performance.
Ill use this generic repository base class again in the following section when I show you how to implement concrete
repositories.
Implementing Concrete Repositories to Manage Contact People in
the System
Implementing a concrete repository is now super simple: just inherit from this generic Repository<T> class and you
get all the CRUD functionality for free. Also, as discussed earlier, the repository should implement an interface that
defines this specific repository. Heres an example of the PeopleRepository:
Whenever you have the need for specialized methods for behavior that is specific for that repository, you can add them
to each repository interface (such as IPeopleRepository) and then implement them in the concrete repository. Heres
an example of a method that finds all contact people by their last name:
1
2
var friendsWithATattoo = repository.FindAll(
x => x.FirstName == "Goo" && x.Type == PersonType.Friend);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[DateCreated] AS [DateCreated],
[Extent1].[DateModified] AS [DateModified],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[DateOfBirth] AS [DateOfBirth],
[Extent1].[Type] AS [Type],
[Extent1].[HomeAddressStreet] AS [HomeAddressStreet],
[Extent1].[HomeAddressZipCode] AS [HomeAddressZipCode],
[Extent1].[HomeAddressCity] AS [HomeAddressCity],
[Extent1].[HomeAddressCountry] AS [HomeAddressCountry],
[Extent1].[HomeAddressContactType] AS [HomeAddressContactType],
[Extent1].[WorkAddressStreet] AS [WorkAddressStreet],
[Extent1].[WorkAddressZipCode] AS [WorkAddressZipCode],
[Extent1].[WorkAddressCity] AS [WorkAddressCity],
[Extent1].[WorkAddressCountry] AS [WorkAddressCountry],
[Extent1].[WorkAddressContactType] AS [WorkAddressContactType]
FROM
[dbo].[People] AS [Extent1]
WHERE
(N'Goo' = [Extent1].[FirstName]) AND (1 = CAST( [Extent1].[Type] AS int))
1
2
3
public class PeopleRepository : Repository<Person>, IPeopleRepository
{
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IPeopleRepository : IRepository<Person, int>
{
IEnumerable<Person> FindByLastName(string lastName);
}


public class PeopleRepository : Repository<Person>, IPeopleRepository
{
public IEnumerable<Person> FindByLastName(string lastName)
{
return DataContextFactory.GetDataContext().Set<Person>().Where(
x => x.LastName == lastName).ToList();
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 83 of 162
Your UI code (such as the MVC project) programs against the interface and thus sees this new method automatically,
ready to be used.
With the model and the repository layer almost done, there are a few small tasks that need to be completed. In the
next section you see how to let the model and EF layer automatically track the creation and modification dates of your
entities. In the final section you see how to improve the error messages that the ContactManagerContext raises to
make debugging easier.
Implementing a Unit of Work
If youve been looking at the code for the repository and the DbContext, you may be wondering how on earth you can
save changes to the DbContext. The repositories (such as PersonRepository) are hiding the fact that a DbSet is being
used under the hood. In addition, no SaveChanges method is defined on IRepository or any of the other repository
types. While you could add this method to the IRepository interface and implement it in Repository<T> for example
(and have it call return DataContextFactory.GetDataContext().SaveChanges(); ), there are better ways to
implement it.
With a unit of work, you typically want to execute one or more updates to the data context, and then save them to the
database at once. Heres an example:
With the implementation of a unit of work in the sample project, you can change this code to this:
At the end of the closing bracket }, SaveChanges is called automatically. So how does this work? You may remember
that a using block in .NET works on objects that implement IDisposable. Under the hood, .NET expands such a block
to a try / finally block and calls Dispose in the finally block. In order to make this code unit testable, you dont
want to hard code a Unit of Work that works with the Entity Framework only. Instead, the sample application has two
interfaces, both located in the Infrastructure project: the IUnitOfWorkFactory and an IUnitOfWork. The
IUnitOfWorkFactory and IUnitOfWork interfaces work together to determine the scope of a unit of work enabling you
send a batch of changes to the database as a single action. The Create method of the factory returns an instance of a
type that inherits IUnitOfWork. This interface in turn inherits IDisposable which forces inheriting types to implement
this method. In the EFUnitOfWork class the Dispose method is used to save the changes to the DbContext. The
IUnitOfWork interface also has Commit and Undo methods to explicitly commit changes to the database, or to get rid
of them. Heres the code for the two interfaces:
1
2
3
4
5
6
var repository = new PeopleRepository();
var person1 = CreatePerson();
repository.Add(person1);
var person2 = CreatePerson();
repository.Add(person2);
repository.SaveChanges(); // Doesn't work because SaveChanges doesn't exist.
1
2
3
4
5
6
7
8
using (new EFUnitOfWorkFactory().Create())
{
var repository = new PeopleRepository();
var person1 = CreatePerson();
repository.Add(person1);
var person2 = CreatePerson();
repository.Add(person2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Spaanjaars.Infrastructure
{
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
IUnitOfWork Create(bool forceNew);
}

public interface IUnitOfWork : IDisposable
{
void Commit(bool resetAfterCommit);
void Undo();
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 84 of 162
In the Repositories.EF project you find the following concrete implementations:
Notice how the Create method of the factory class forwards the value of the forceNew parameter to the constructor of
EFUnitOfWork. This value is then used to determine if the context should be cleared or not. Remember the
DataContextStorage I showed earlier? The Clear method ensures that the current DbContext is cleared, so a new
one is created the next time GetDataContext is called. I typically use the parameterless version of Create in
production code while I use the second overload in integration testing. By ensuring that any data context is cleared
when you run an integration test, you make sure that a problem caused in one test is not causing other tests to fail.
This in turn makes it easier to find issues in your tests and fix them.
To see how the changes are saved, take a look at the Dispose method:
When Dispose is called, SaveChanges is called on the same DbContext that the repository has been using.
To see how it all fits together, take another look at the same code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
namespace Spaanjaars.ContactManager45.Repositories.EF
{
public class EFUnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork Create()
{
return Create(false);
}

public IUnitOfWork Create(bool forceNew)
{
return new EFUnitOfWork(forceNew);
}
}

public class EFUnitOfWork : IUnitOfWork
{
public EFUnitOfWork(bool forceNewContext)
{
if (forceNewContext)
{
DataContextFactory.Clear();
}
}

public void Dispose()
{
DataContextFactory.GetDataContext().SaveChanges();
}

public void Commit(bool resetAfterCommit)
{
DataContextFactory.GetDataContext().SaveChanges();
if (resetAfterCommit)
{
DataContextFactory.Clear();
}
}

public void Undo()
{
DataContextFactory.Clear();
}
}
}
1
2
3
4
public void Dispose()
{
DataContextFactory.GetDataContext().SaveChanges();
}
1 using (new EFUnitOfWorkFactory().Create())
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 85 of 162
Because of the using block, .NET expands this to the following (pseudo code):
The IUnitOfWork interface also exposes a Commit method and an Undo method. Commit calls SaveChanges as well and
can be used if you want to explicitly save the changes without relying on the automatic save behavior of the unit of
work. You see this method at work in Part 9 of this series which discusses a command line import tool. Undo can be
used to undo any pending changes which can be useful if you change your mind about the data (for example, when an
entity is in an invalid state) while in a unit of work. Undo simply clears the DbContext from the container which means
a new DataContext instance is created the next time GetDataContext is called.
The code in the try block creates a new PeopleRepository and adds two people to them. The Add method uses
DataContextFactory.GetDataContext() under the hood to get a reference to the DbContext stored in HttpContext
or the current thread. When the finally block is hit, Dispose is called which gets a reference to the same DbContext
and then calls SaveChanges on it to send all the updates to the database.
Because the unit of work is based on interfaces, its easy to use them in unit testable environments. For example, you
could use them as follows in an MVC controller:
In this example, the controller receives an instance of IPeopleRepository and an instance of IUnitOfWorkFactory.
Both parameters to the constructor are based on interfaces so its easy to pass other types during unit testing. At
run-time, in production, a dependency framework injects concrete EF-based versions of the classes that access your
production database. You see how to enable dependency injection in the next article in this series.
2
3
4
5
6
7
8
{
var repository = new PeopleRepository();
var person1 = CreatePerson();
repository.Add(person1);
var person2 = CreatePerson();
repository.Add(person2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
var uow = new EFUnitOfWorkFactory().Create();
try
{
var repository = new PeopleRepository();
var person1 = CreatePerson();
repository.Add(person1);
var person2 = CreatePerson();
repository.Add(person2);
}
finally
{
uow.Dispose();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class HomeController : Controller
{
private readonly IPeopleRepository _peopleRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;

public HomeController(IPeopleRepository peopleRepository,
IUnitOfWorkFactory unitOfWorkFactory)
{
_peopleRepository = peopleRepository;
_unitOfWorkFactory = unitOfWorkFactory;
}

[HttpDelete]
public ActionResult Delete(int id)
{
using (_unitOfWorkFactory.Create())
{
_peopleRepository.Remove(id);
}
return RedirectToAction("Index");
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 86 of 162
In the Delete method, the call to Create on _unitOfWorkFactory returns an instance of a class that implements
IUnitOfWork. In a production application, that would be an EFUnitOfWork which persists the changes to the database
(deleting a Person based on the id parameter) by calling SaveChanges.
Just like other code from this article, this may seem like a lot of work to implement something simple as a call to
SaveChanges. However, once again, a lot of it is plumbing code so you only need to write it once. And once the code is
written, saving changes in a single step is now as simple as wrapping some code in a using block.
Using the model and repositories presented in this and the precious article makes your application a lot easier to
change. In the previous version of my N-Layer design, when you wanted to add a property to a class, you needed to
update the following:
Add the property to the dumb data object.
Modify the DB class and add support for the new property in the Save and FillDataRecord methods.
Modify multiple stored procedures to include the field in the various select and insert / update procedures.
Use the field in the UI.
With the new implementation, you can bring this down to two steps:
Add the property to the model class.
Use the new field in the UI.
Obviously you may still need to write some code to configure the property and its validation rules, but the fact you
don't have to mess with multiple stored procedures (or any data access code at all) is a big time saver.
Managing Relationships
In Part 4 of this series I mentioned a problem with the collections and removal of the contact details. I showed the
following example:
Now that the repositories are done, I can rewrite the code as follows:
Both these example have the same problem. When the changes are saved, any e-mail address that belonged to this
person is not deleted from the database. Instead, the OwnerId is set to null, effectively orphaning the e-mail address
record.
To work around this issue you need to tell EF what to do with these objects. The logic to determine which objects to
delete is relatively simple: e-mail addresses and phone numbers that no longer have an owner. Thats the reason I
implemented the IHasOwner interface which you can use for entities that are owned by other entities, and which
should be removed from the database whenever they are removed from the parent collection. Once youve found the
objects you want to delete, setting their State to EntityState.Deleted is then enough for EF to delete them from the
database. The best place to implement this code is in an override of SaveChanges on the ContactManagerContext
which is called by EF whenever it saves the changes. Heres the code from the sample application:
1
2
3
var person = myContext.People.First(x => x.Id = id);
person.EmailAddresses.Clear();
myContext.SaveChanges();
1
2
3
4
5
using (_unitOfWorkFactory.Create())
{
var person = _peopleRepository.FindById(id, x => x.EmailAddesses);
person.EmailAddresses.Clear();
}
1
2
3
4
5
6
7
8
9
10
public override int SaveChanges()
{
var orphanedObjects = ChangeTracker.Entries().Where(
e => (e.State == EntityState.Modified || e.State == EntityState.Added) &&
e.Entity is IHasOwner && e.Reference("Owner").CurrentValue == null);

foreach (var orphanedObject in orphanedObjects)
{
orphanedObject.State = EntityState.Deleted;
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 87 of 162
This code finds all entities that are either modified or added in the current session. It then tries to cast them to an
IHasOwner which will only work for EmailAddress and PhoneNumber instances. It also checks the reference called
Owner to see if its null (and thus an orphaned entity). I dont like the hardcoded string of Owner much, but since
the interface IHasOwner guarantees that the related entities have a property called Owner, I am OK with this magic
string. Finally, the code sets the State of all entities found to Deleted.
You can find the article I used to come up with this solution here: http://www.phdesign.com.au/programming/delete-
dependent-entities-when-removed-from-ef-collection/ while an alternative solution using a attribute can be found
here: http://wimpool.nl/blog/DotNet/extending-entity-framework-4-with-parentvalidator.
With these changes, the objects are now deleted from their associated tables in the database. For more details about
this solution, check out this blog post: http://www.phdesign.com.au/programming/delete-dependent-entities-
when-removed-from-ef-collection/.
Note that for this to work correctly, the related entities must be loaded into the Person instance. Entities that werent
loaded when you call Clear() wont be deleted from the database.
Implementing IDateTracking
As I mentioned earlier, a common requirement in a data driven application like the Contact Manager is to automatically
track when an entity was created and when it was last updated. In Part 4 you saw how I created the IDateTracking
interface to force entities to implement DateCreated and DateModified properties. While you could manually set
these properties, it would be much nicer if they were updated automatically for you.
Using EF, this is pretty simple to implement in the model and data layer, with a minimum amount of code. All you need
to do is override SaveChanges in the ContactManagerContext class, find all added and modified entities, update their
dates and then let EF save the changes to the database. Heres how the code in SaveChanges looks (in the sample
project its wrapped in a try block to improve error messages as youll see in the next section of this article):
This code uses the Entries collection of the built-in ChangeTracker to find all objects that have been added or
changed in the latest session (e.g. since the data context was created, or since SaveChanges was called last). The
code then loops over these entries and tries to cast them to the IDateTracking interface using the as keyword. If that
works, the class implements this interface and the two properties can be set. The code uses the entitys State
property to determine if its a new entity or an existing entity thats being modified. Only in the former case is the
DateCreated property set; in both cases the DateModified property is filled with the current date. If you dont like
this and prefer to have new entities that have an empty (null) DateModified, you can change the code in the
SaveChanges method and make the property nullable to accommodate for this.
With this change, all entities that implement this interface will now automatically track their creation and modification
11
12
13

... Other code here
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public override int SaveChanges()
{
... Other code here

var modified = ChangeTracker.Entries().Where(
e => e.State == EntityState.Modified || e.State == EntityState.Added);

foreach (DbEntityEntry item in modified)
{
var changedOrAddedItem = item.Entity as IDateTracking;
if (changedOrAddedItem!= null)
{
if (item.State == EntityState.Added)
{
changedOrAddedItem.DateCreated = DateTime.Now;
}
changedOrAddedItem.DateModified = DateTime.Now;
}
}
return base.SaveChanges();
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 88 of 162
dates. Figure 5-6 shows the People table in the database with the two new properties:
(6) See Links in this Document at the end for the full URL of this image.
Figure 5-6 The People table
Improving Error Messages Generated by the DbContext
Whenever an error occurs while saving entities, the Entity Framework throws a rather cryptic error message. For
example, when you save an entity that is missing a required field, you get an error like the following:
(7) See Links in this Document at the end for the full URL of this image.
Figure 5-7 The Standard EF Error Message
This message tells you nothing about the actual validation error, why validation failed, or which entity was invalid. With
a bit of code you can make the error message read as follows:
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 89 of 162
(8) See Links in this Document at the end for the full URL of this image.
Figure 5-8 Improved Error Messages
Notice how the error message now mentions the invalid entitys type, ID (if it exists) and the reason it was invalid.
This becomes even more useful if youre updating multiple entities at the same time with multiple validation errors:
(9) See Links in this Document at the end for the full URL of this image.
Figure 5-9 Multiple Error Messages
In order to get the more detailed information, I added the following code to the SaveChanges method in the
ContactManagerContext class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public override int SaveChanges()
{
try
{
// Other code here
return base.SaveChanges();
}
catch (DbEntityValidationException entityException)
{
var errors = entityException.EntityValidationErrors;
var result = new StringBuilder();
var allErrors = new List<ValidationResult>();
foreach (var error in errors)
{
foreach (var validationError in error.ValidationErrors)
{
result.AppendFormat("\r\n Entity of type {0} has validation error \"{1}\" for
property {2}.\r\n", error.Entry.Entity.GetType().ToString(),
validationError.ErrorMessage, validationError.PropertyName);
var domainEntity = error.Entry.Entity as DomainEntity<int>;
if (domainEntity != null)
{
result.Append(domainEntity.IsTransient() ? " This entity was added
in this session.\r\n" : string.Format("The Id of the entity is {0}.\r\n",
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 90 of 162
This code uses a try/catch block to catch an EF DbEntityValidationException. It then loops over the validation
errors, building up a StringBuilder with the error messages and type information. Notice how it uses the
IsTransient method of the DomainEntity base class to determine if the object is new or already existed in the
database. In the end, the code raises a new exception of type ModelValidationException, wraps the original
exception and provides the detailed error information as the ErrorMessage. The ModelValidationException class is a
custom Exception type defined in the Infrastructure project. Its mostly just a standard Exception but has a
constructor overload that accepts an IEnumerable<ValidationResult> and that exposes those again using a
read-only property. This property can be queried by calling code to find out what went wrong during a database
update. You see a concrete example of this in Part 6 of this series.
Note: Using error handling like this may expose more data than you want. Make sure you never show errors like this
on the production server using custom errors or a framework like Elmah. You could also modify this code so it only
runs on a developers machine, or in debug mode.
Stuff I Like to Do
Write integration tests for the Repository classes. Even though they are based on a generic base class that I
can test separately, its still useful to have test methods that ensure you can correctly retrieve data from the
database and send it back again.
Write integration tests that test the behavior of related entities. Setting up an EF model can be tricky especially
when multiple related entities are involved. By writing tests that assert that data gets deleted when you expect
it helps to ensure the correctness of your model and the interaction with the database.
Summary
This article covered a lot of ground. Youve seen how to build the data context (that inherits from DbContext) and how
to store it in a container appropriate for the type of application (web versus other types of applications). You also saw
how to implement validation rules using attributes, the fluent API, and using object level validation using the
IValidatableObject interface.
A fair part of this article was spent discussing repositories. You saw how to implement a generic Repository<T> that
can be used as a base class, without limiting you in the options to expand your specific repositories with more
specialized behavior. You also saw how to implement a Unit of Work to send a batch of changes to the database in one
fell swoop.
At the end you saw how to override the SaveChanges method of the DbContext to implement date tracking and
improve EFs error messages.
This is also the end of the part of this article series that deals with the model and repositories; i.e. the part of the
application you dont see but thats used a lot under the hood of the UI projects. In the following four parts you see
how to make use of this framework in an MVC 4 project, a Web Forms 4.5 project, a WCF service project and a
Console application.
Links in this Document
(1) http://nhforge.org/
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-1_NuGet_Install_EF.png
(3) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-2_Row_Inserted.png
(4) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05
/Figure5-3_Class_Diagram_Context_Storage.png
(5) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-4_Error_Running_UnitTest.png
(6) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-6_People_Table_IDateTracking.png
(7) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-7_EF_Validation_Error.png
25
26
27
28
29
30
31
32
33
domainEntity.Id));
}
allErrors.Add(new ValidationResult(validationError.ErrorMessage, new[] {
validationError.PropertyName }));
}
}
throw new ModelValidationException(result.ToString(), entityException, allErrors);
}
}
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 91 of 162
(8) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-8_EF_Better_Validation_Error.png
(9) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part05/Figure5-9_EF_Multiple_Validation_Errors.png
ASP.NET N-Layered Applications - Implementing a Repository using EF Code First (Part 5)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 92 of 162
ASP.NET N-Layered Applications - Implementing an ASP.NET
MVC 4 Frontend (Part 6)
This is Part 6 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a Web UI using ASP.NET MVC 4 and make use of the model
and repository projects I have shown in the past five articles.
Introduction
In the past couple of years, ASP.NET MVC has become a very popular framework for building web sites on the
Microsoft platform. The current version is ASP.NET MVC 4 and it ships with Visual Studio 2012 although you can also
download it separately for Visual Studio 2010.
This article is not meant as an introduction to ASP.NET MVC. If youre new to MVC, I recommend checking out the
following resources:
Getting Started with MVC (http://www.asp.net/mvc)
Intro to ASP.NET MVC 4 (http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-
to-aspnet-mvc-4)
Pro ASP.NET MVC 4, Adam Freeman (Apress, 2013, http://www.amazon.com/Pro-ASP-NET-MVC-
Adam-Freeman/dp/1430242361/)
In this article, Ill show you how to use the repositories and model from an ASP.NET MVC 4 application. Ill cover the
following topics:
How to use Dependency Injection to determine the type of the repository at run-time.
How to use the validation functionality of the model in the UI.
How to use the Unit of Work pattern to save changes to the database as a batch.
In Part 2 of this article series you saw how to add the MVC 4 project to the solution. I used the Internet application
type as the starting point which gives you a bunch of controllers and views that define the global look and feel of the
site. To make it easy to see whats going on, I havent changed much in the original layout files that ship with a new
ASP.NET MVC 4 Razor project. I made a few minor changes to align the design with the one from the Web Forms
sample application but thats it. If youre familiar with the ASP.NET MVC 4 standard projects, youll feel right at home.
In Part 1, Ive provided a brief overview of the sample application and showed you a few screenshots. Heres a brief
recap of what the application can do. Remember: the purpose of this article series and this demo web site is to show
you how to design an application from an architecture point of view. The demo does not offer a complete feature set
as you would normally build in real-world web sites such as a fancy UI.
When you start up the application you see the home screen with a short welcome text. When you click the People
menu, you see all the contact people in the system with links to edit and delete them, and to manage their contact
data:
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 93 of 162
(1) See Links in this Document at the end for the full URL of this image.
Figure 6-1 The People List
Using the Edit link you can modify the details of an individual contact person, using the following page:
(2) See Links in this Document at the end for the full URL of this image.
Figure 6-2 Editing a Single Contact Person
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 94 of 162
When you click one of the address links (shown in Figure 6-1), you see a screen that lets you manage address details.
In this case, the user already pressed the Save button and the validation (from the Address class in the Model project)
kicked in:
(3) See Links in this Document at the end for the full URL of this image.
Figure 6-3 Validation at Work when Editing an Address
When you click the Email addresses or Phone numbers link (shwon in Figure 6-1) you see a list of associated contact
records for that user:
(4) See Links in this Document at the end for the full URL of this image.
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 95 of 162
Figure 6-4 Managing E-mail Addresses
From here, you can manage the existing addresses (view details, edit and delete) as well as create new addresses for
this contact person.
The About page provides more background on the application and the Contact page can be used to get in touch with
me. The Register and Login links at the top come from the standard MVC template. They are fully functional, but not
used in the sample application.
Under the hood, this MVC application uses the PeopleRepository targeting the Entity Framework for all data access.
The list of people is retrieved using FindAll, a details page uses FindById, and the insert pages use Add, and so on.
To see how it all fits together, heres the architecture diagram showing the MVC frontend and how its related to the
other components in the system:
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 96 of 162
(5) See Links in this Document at the end for the full URL of this image.
Figure 6-5 The N-Layer Architecture Diagram
To make your MVC controllers unit testable, its important that none of them have direct ties with the Entity
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 97 of 162
Framework implementation of the PeopleRepository. Direct access from controllers to EF would mean that you need
a real database when running the tests which makes things slower and harder to test. The Controller classes in the
project should exchange model entities from the Model project through an abstraction (the IPeopleRepository
interface) instead, as you see how to do in the next section.
Making your Controllers Testable
To see why you want to work with an abstraction rather than a concrete implementation of the PeopleRepository,
consider this (fictitious) action method in the PeopleController:
This method instantiates a PeopleRepository, and then retrieves a sub set of the contact people based on the sorting
and paging data. A unit test for this method could look like this:
At first glance, this may look perfectly reasonable. The code creates a new controller, executes the List method and
then asserts that the total number of records is 10 (the default page size for the system) and that the first person in
the list (the youngest contact person in the system because the code sorted on DateOfBirth in descending order), is
born on December 1st, 2007.
If you ran this test, it might just work. However, it only works under special conditions: you must have a least 10
contact people in your database, and the youngest person must be born on December 1st, 2007. While you could
certainly insert default data (using the Seed method of the database initializer, using Red Gates Data Generator or in
the constructor or method body of the unit test), this is asking for trouble, What if you have other unit tests that test
changing the date of birth or deleting all contact people from the system? If those tests were run before
ListSortsAndPagesCorrectly, things would surely break.
On top of that, you dont really care about testing the behavior of the PeopleRepository as youre doing that
elsewhere already (in the Unit and Integration tests projects). What you care about here is the List method: given an
IPeopleRepository, you want this method to call FindAll, and then apply the proper sorting and paging settings.
The solution to this problem is to provide a fake repository that provides temporary data. You could have only one for
your entire test project, or you could have many, each serving a distinct purpose. Heres how you could write such an
IPeopleRepository:
1
2
3
4
5
6
public ActionResult List(int page = 1, string sort = "Id", string sortDir = "ASC")
{
IQueryable<Person> allPeople = new PeopleRepository().FindAll().OrderBy(
BuildOrderBy(sort, sortDir)).Skip((page * pageSize) - pageSize).Take(pageSize);
return View(allPeople);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[TestMethod]
public void ListSortsAndPagesCorrectly()
{
// Arrange
var controller = new PeopleController();

// Act
var result = controller.List(1, "DateOfBirth", "DESC") as ViewResult;

// Assert
IEnumerable<Person> modelData = ((IEnumerable<Person>)result.Model).ToList();
modelData.Count().Should().Be(10);
modelData.First().DateOfBirth.Year.Should().Be((2007));
modelData.First().DateOfBirth.Month.Should().Be((12));
modelData.First().DateOfBirth.Day.Should().Be((1));
}
1
2
3
4
5
6
7
8
internal class FakePeopleRepository : IPeopleRepository
{
public IQueryable<Person> FindAll(
params System.Linq.Expressions.Expression<Func<Person, object>>[] includeProperties)
{
var temp = new List<Person>();
var youngestPerson = new DateTime(2007, 12, 1);
for (int i = 0; i < 23; i++)
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 98 of 162
This fake repository returns a list of 24 people when you call the FindAll method. The youngest person in the list is
born on December 1st, 2007; all the other people are slightly older. All the other methods are not implemented as I
dont care about them for this particular test. For other tests, I could implement these methods, or create another fake
repository where I only implement the methods used by my test code.
Using this fake PeopleRepository, its now much easier to test the List method. And even better: you only test the
List method. You no longer have a dependency on the real EF PeopleRepository, nor do you require a database with
the correct data in it. This frees you from a lot of unnecessary dependencies, so you can let your test method focus on
one thing, and one thing only: the code inside the List method of your MVC controller.
In order for the List method to use this repository, you need a way to pass it to the controller. Ill show you a quick
and dirty way first (referred to as poor mans dependency injection) so you understand the core principles. In a later
section you see a better solution by using a dependency injection framework that resolves all dependencies for you
automatically.
As I mentioned earlier, the controller needs access to the FakeRepository so you need to find a way to pass it in.
Passing it to the List method wont work as the MVC runtime wouldnt know how to supply one. You could instantiate
one directly in your code inside the action method (just as I did previously with the EF PeopleRepository) but that
doesnt make the situation any better. How would you know when to supply which one? For this to work, you would
need a way to differentiate between a regular run-time, and the unit testing run-time which really isnt the direction
you want to take things.
Fortunately, there is a much easier way: simply pass the required dependencies through an overloaded constructor of
the controller. In the default constructor (the parameterless version that gets called by the MVC framework) you then
instantiate an EF PeopleRepository directly. Something like this would do the trick:
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
temp.Add(new Person { FirstName = i.ToString(), LastName = i.ToString(),
DateOfBirth = youngestPerson.AddDays(-i) });
}
temp.Insert(11, new Person { FirstName = "Youngest", LastName = "Youngest Lastname",
DateOfBirth = youngestPerson });
return temp.AsQueryable();
}

public void Add(Person entity)
{
throw new NotImplementedException();
}

public void Remove(Person entity)
{
throw new NotImplementedException();
}

// Other methods (none of them implemented) go here
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class PeopleController : Controller
{
private readonly IPeopleRepository _peopleRepository;

public PeopleController(IPeopleRepository peopleRepository)
{
_peopleRepository = peopleRepository;
}

public PeopleController() : this(new PeopleRepository())
{
}

public ActionResult List(int page = 1, string sort = "Id", string sortDir = "ASC")
{
IQueryable<Person> allPeople = _peopleRepository.FindAll().OrderBy(BuildOrderBy(
sort, sortDir)).Skip((page * pageSize) - pageSize).Take(pageSize);
return View(allPeople);
}
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 99 of 162
The parameterless version ensures everything keeps working like normal. When a URL like /People/List is requested,
the constructor sends a new instance of PeopleRepository into the overloaded constructor which stores that object in
the _peopleRepository variable. Then, when List is called, it uses that variable to call the FindAll method which
eventually queries the SQL Server database using the Entity Framework.
For your unit test you can now use the overloaded constructor, and pass in your fake repository like this:
Now the controller receives an instance of your FakeRepository. Since you can control the objects returned from
FindAll method in the fake repository, its easy to set up the correct asserts for things like the data being returned.
This effectively decouples your unit test (and your MVC controller) from the database dependency. This in turn makes
life a lot simpler, leading to easier unit testing, and minimizing the chances that your tests fail for the wrong reasons.
In the sample application you see this implemented in a very similar way. Rather than List, the action method is
called Index, and its accompanying test method is called IndexSortsAndPagesCorrectly inside the
PeopleControllerTests class. The implementation differs in that the controllers constructor expects another
dependency: an IUnitOfWorkFactory. Since thats not used for this test, the test method simply passes null:
Youll see more of the IUnitOfWorkFactory dependency later.
While the solution with the parameterless constructor that forwards an instance of the EF PeopleRepository is nice,
theres an even better way: you can tell an external framework to provide the concrete instances at runtime for you.
You see how this works in the next section.
Injecting Repositories using StructureMap
Manually modifying your constructors to support dependency injection is quite labor intensive, and prone to errors.
Every time you add another dependency, you should not forget to update the parameterless constructor. In addition,
since youre testing another constructor than the one that MVC calls, theres still a slim chance of bugs in your system
that go unnoticed in your tests. Fortunately, theres a solution to the problem: a Dependency Injection (DI) framework.
ASP.NET MVC has been designed with testability in mind and as such its pretty easy to plug a DI framework into the
runtime. This DI framework then ensures that when a controller has dependencies (such as the IPeopleRepository in
the controllers constructor), they are automatically instantiated. And even cooler, if the dependency itself has another
dependency, the framework will ensure proper initialization of that dependency as well. So in the sample application,
whenever a controller is instantiated, it automatically receives concrete instances of the IPeopleRepository and
IUnitOfWork interfaces. You see how the framework can determine which concrete type to instantiate in a later
section.
Many different DI frameworks exist, including Unity, Castle Windsor, StructureMap, Ninject, and AutoFac. For a
deep-dive into DI, and the different DI frameworks, check out:
Dependency Injection in .NET (Mark Seemann, Manning, 2011)
(6)
http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[TestMethod]
public void ListSortsAndPagesCorrectly()
{
// Arrange
var controller = new PeopleController(new FakePeopleRepository());

// Act
var result = controller.List(1, "DateOfBirth", "DESC") as ViewResult;

// Assert
IEnumerable<Person> modelData = ((IEnumerable<Person>)result.Model).ToList();
modelData.Count().Should().Be(10);
modelData.First().DateOfBirth.Year.Should().Be((2007));
modelData.First().DateOfBirth.Month.Should().Be((12));
modelData.First().DateOfBirth.Day.Should().Be((1));
}
1 var controller = new PeopleController(new FakePeopleRepository(), null);
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 100 of 162
In my sample application, I am using StructureMap
(7)
as the DI container. I chose it as I find it pretty much
hassle-free to work with. However, I could have easily chosen a different framework as the DI requirements for the
sample application can be fulfilled by all of the major DI frameworks.
To add and configure StructureMap in an MVC app, you need to do the following:
Add the StructureMap.MVC4 package to your MVC project using NuGet. This also brings in the dependent
StructureMap package.
1.
Write some code to tell the DI component how to resolve types like IPeopleRepository into their concrete
counterparts.
2.
Adding the StructureMap.MVC4 Package using NuGet
To add StructureMap to your MVC project, follow these steps:
Open up the Package Manager Console by choosing Tools | Library Package Manager | Package Manager
Console
1.
Select your MVC project from the Default project drop-down. 2.
At the command, type Install-Package StructureMap.Mvc4 and hit enter. 3.
This package makes the following modifications:
In App_Start it adds StructuremapMvc.cs which is a class that initializes the StructureMap framework and
then registers itself as the dependency resolver for the MVC framework.
1.
It adds the folder DependencyResolution with three code files with code needed to setup StructureMap. Of
those three, you only need to modify IoC.cs for your application.
2.
Write Code to Tell the DI Component how to Resolve Types
Whenever the DI container needs to resolve a dependency it needs to understand what to do. For example, when an
IPeopleRepository is needed, the container needs to know it should return an instance of the PeopleRepository
from the EF project. The exact type to be returned is configurable to give you the greatest flexibility. To see how this
works, look in IoC.cs in the DependencyResolution folder that has been added to your project. You should see the
following Initialize method:
Although the code looks a bit cryptic with all the lambdas, its relatively straightforward. The call to
TheCallingAssembly tells the framework to scan the assembly that is making the call (which by default is the MVC
project to which you added StructureMap). The call to WithDefaultConventions means: whenever an ISomething is
requested, try to return a Something (that should then implement the ISomething interface). In other words, it tries
to find a concrete type named after the interface by dropping the I from the interface name.
This is a good setup if you have all your code inside the MVC project and if all your classes and interfaces follow the
default conventions. In the sample application, the concrete types are not located in the MVC assembly, but rather in
the one from the Repositories.EF project. You could include that assembly specifically, or for maximum flexibility you
can call AssembliesFromApplicationBaseDirectory as youll see shortly. Note that IUnitOfWorkFactory is not
implemented by a class called UnitOfWorkFactory, but rather by one called EFUnitOfWorkFactory. You can use the
For method to explicitly link base types and interfaces to concrete types. My final Initialize method now looks like
this:
1
2
3
4
5
6
7
8
9
10
11
12
13
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
// x.For<IExample>().Use<Example>();
});
return ObjectFactory.Container;
}
1
2
3
public static IContainer Initialize()
{
ObjectFactory.Initialize(scanner =>
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 101 of 162
For more information about the scanning process and conventions, check out the documentation for StructureMap:
http://docs.structuremap.net/ScanningAssemblies.htm.
With this code in place, I can now simplify the code of the PeopleController so it only has a single constructor:
Now, whenever a new instance of the PeopleController is needed, StructureMap kicks in and supplies concrete
instances of the PeopleRepository and UnitOfWorkFactory.
Note: rather than directly inheriting Controller, this class inherits BaseController which in turn inherits the MVC
Controller class. By using a centralized base class for your controllers its easy to add behavior that applies to all
controllers in your project.
With the dependencies taken care of, the next step is implementing the methods inside the PeopleController as well
as the implementation of the views. Again, since this is not an article series about MVC, I wont dig into each and
every method or code sample. Youre encouraged to download and inspect the source for this article series so you get
a better understanding of what it does and how.
Building the PeopleController and its Views
In this section youll see how I implemented the PeopleController with methods to list, display, create, edit, and
delete contact people. The other controllers follow similar patterns, although the exact implementation differs here and
there.
Index / List
In this section, Ill show you different versions of an Index method, each one adding more functionality. At the end, Ill
show the final version that is used in the PeopleController of the sample application. The final action method
supports a pageable and sortable display of contact people.
If all you want to show on your List page are all items of a specific type such as people (usually shown using the Index
method), implementing the action method would be extremely simple. All you would need is something like this:
4
5
6
7
8
9
10
11
12
13
14
{
scanner.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.WithDefaultConventions();
});

scanner.For<IUnitOfWorkFactory>().Use<EFUnitOfWorkFactory>();
});
return ObjectFactory.Container;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PeopleController : BaseController
{
private readonly IPeopleRepository _peopleRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
const int pageSize = 10;

public PeopleController(IPeopleRepository peopleRepository, IUnitOfWorkFactory unitOfWorkFactory)
{
_peopleRepository = peopleRepository;
_unitOfWorkFactory = unitOfWorkFactory;
}

public ActionResult Index(int page = 1, string sort = "Id", string sortDir = "ASC")
{
// Implementation goes here; uses _peopleRepository
}
}
1
2
3
4
public ActionResult Index()
{
return View(_peopleRepository.FindAll());
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 102 of 162
This would work fine if you only have a few records to show, and if you dont care about sorting the data. A simple
view like the following would suffice:
However, this controller and view have a few issues:
The view is using the Person entity from the Model project directly, While this works, I typically try to stay
away from it as I dont want my views to know about the actual model; I could be exposing too much data to
the view, or the view could be making changes to the entity if it was in an updateable state. Instead, I prefer
to create a View Model that has only the fields I want to expose in my view, and then use a mapping
framework to automatically convert my entities (such as a Person) into the corresponding View Model (such
as a DisplayPerson, dedicated to displaying contact people).
1.
There is no support for paging; if your database table contains hundreds or thousands or more records, the
list becomes really hard to manage and the page will load much slower.
2.
There is no way to sort data. 3.
To see where View Models are used, consider this architecture diagram that shows the four frontend applications:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@model IEnumerable<Spaanjaars.ContactManager45.Model.Person>
@{
ViewBag.Title = "Index";
}
<h2>@ViewBag.Title</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.FullName)
</th>
<th>
@Html.DisplayNameFor(model => model.DateOfBirth)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.FullName)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateOfBirth)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { id = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 103 of 162
(8) See Links in this Document at the end for the full URL of this image.
Figure 6-6 View Models in the Architecture Diagram
In the MVC project, View Models are used to pass data from the controllers to the views and vice versa. This means
that a view never has to know of the existence of one of the Model types; it only needs to know of the View Model
types. In the WCF project, View Models are used to exchange data between the service methods and the external
system that call the service methods so there is never a direct dependency on the Model types and the external
applications. The other two frontend applications dont use View Models although you could introduce them there as
well if you have the need.
You see how to implement View Models in MVC next; the WCF View Models are discussed in Part 8.
Creating a View Model
To determine how a View Model for a specific type needs to look, you need to think about the data you want to expose,
and what the View Model is used for. Although you could create one View Model per entity, I prefer to create multiple
View Models per entity to support different models for different actions. For example, a View Model used to display a
Person has different requirements than a View Model used to create or edit a Person.
When displaying a Person, you most likely want to display the FullName and the DateOfBirth in a list. For a details
page, you may also want to display things like the type, the creation and modification dates and more. In a more
complex application, you could decide to create two separate models for this. In the sample application, I chose to
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 104 of 162
combine them in single View Model called DisplayPerson:
Notice how I left out the two collections (EmailAddresses and PhoneNumbers) and the two Address properties as you
typically dont display that information in a list or details page for a Person.
To convert a Person (or even a collection of Person instances) into a DisplayPerson you could write a lot of manual
code that instantiates a new DisplayPerson and then copies over the property values one by one. However, this is
quite a bit of work, and its likely to break when you add new properties to the Person type or the DisplayPerson.
Instead, I prefer to use a framework called AutoMapper
(9)
. Ill show the code for the view that displays instances of
the DisplayPerson View Model later.
Mapping with AutoMapper
To see what problem AutoMapper solves, imagine you have an entity type called Car, like this:
If you want to display cars in a list, its corresponding View Model could look like this:
This model is designed to just hold the cars ID and name. Inside your controller you could map a Car to a
CarViewModel like this:
This is pretty straightforward code. A Car instance is retrieved from a repository, a new instance of CarViewModel is
created, the values for the members exposed by CarViewModel are copied from the Car instance and finally the View
Model is fed to the view. In this example, things are relatively simple because CarViewModel has only two properties,
but this gets messy pretty quickly when the View Model has many members. With AutoMapper, this can be changed to
this:
1
2
3
4
5
6
7
8
9
10
11
public class DisplayPerson
{
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public PersonType Type { get; set; }
}
1
2
3
4
5
6
7
8
public class Car
{
public int Id { get; set; }
public string Name { get; set; }
public int NumberOfDoors { get; set; }
public EngineType { get; set; }
// Lots of other properties here
}
1
2
3
4
5
public class CarViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
1
2
3
4
5
Car car = _carRepository.FindById(id);
CarViewModel carViewModel = new CarViewModel();
carViewModel.Id = car.Id;
carViewModel.Name = car.Name;
return View(carViewModel);
1
2
3
Car car = _carRepository.FindById(id);
CarViewModel carViewModel = new CarViewModel();
Mapper.Map(car, carViewModel);
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 105 of 162
In this example, you save only one line of code. However, even with complex types with many members, this is all you
need, saving you from lots of typing overhead and greatly reducing the risk of errors during the conversion.
AutoMapper is able to automatically map members of two types if they have the same name and type. If your View
Model uses different names, or if you want to exclude members from one type or the other, or if you want to change
how data is mapped, you can configure AutoMapper using its API. This is code you need to write once for each type
and then AutoMapper will use that configuration every time it needs to map a type. To see how this works, you need to
add AutoMapper to your project first. Once again, a NuGet project is available to make this dead-simple:
Open up the Package Manager Console window. In the Default project drop-down select the MVC project.
At the command prompt, type Install-Package AutoMapper and hit enter.
For the sample application I also created a code file called AutoMapperConfig inside the App_Start folder and
added the following code to map from a Person to a DisplayPerson (as per the code shown earlier):
Since all fields of DisplayPerson also exist in Person, this is all I need to add for AutoMapper to figure out the
mapping rules. Youll see a more extensive example later when editing a contact person is discussed.
Notice the call to AssertConfigurationIsValid. This triggers AutoMapper to validate all mappings, and throw an
error when it finds unmatched members or other errors in your mappings. This helps to catch errors as soon as
possible.
Finally, I added the following line of code in Global.asax:
With this code, whenever the application starts, AutoMapper is initialized; all mappings are created and then validated.
From then on, all you need is a call to Map to have AutoMapper create the mapping.
With AutoMapper setup in the sample project I could now rewrite my Action method like this:
Just as in the previous example, I get all contact people from the database using FindAll method. Whats different is
that I now use AutoMapper to map from a Person instance to a DisplayPerson instance. And not only that,
AutoMapper also understands how to deal with collections. So, even though the people variable is actually an
IQueryable<Person>, AutoMapper knows how to convert that into a List<DisplayPerson> which is eventually passed
to the view.
For more information on AutoMapper, check out the following resources:
4 return View(carViewModel);
1
2
3
4
5
6
7
8
9
10
11
public static class AutoMapperConfig
{
public static void Start()
{
Mapper.CreateMap<Person, DisplayPerson>();

// Other mappings go here

Mapper.AssertConfigurationIsValid();
}
}
1
2
3
4
5
protected void Application_Start()
{
...
AutoMapperConfig.Start();
}
1
2
3
4
5
6
7
public ActionResult Index()
{
var people = _peopleRepository.FindAll();
var model = new List<DisplayPerson>();
Mapper.Map(people, model);
return View(model);
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 106 of 162
https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
https://github.com/AutoMapper/AutoMapper/wiki
http://automapper.org/
Before I show you the code that would be needed for the view, lets make a few more changes to the Index method to
support paging and sorting, as this also effects the View Model.
Sorting Data
LINQ to EF has great support for sorting. Just call OrderBy and OrderByDescending to order a collection based on a
lambda expression, For example, this code sorts all people on their birth date:
What LINQ to EF, or actually, LINQ in general is not good at is sorting based on strings. Quite often, in a UI driven
application, the sort order comes from a string entered by the user (for example, by clicking the header of a grid).
Ideally, you would like to apply sorting as follows:
Out of the box, this wont work as there is no overload of OrderBy that accepts a string. However, Microsoft
developed and released the DynamicQuery library that lets you perform string based ordering, searching and more.
And it probably comes as no surprise: its available as a NuGet package
Note: if youre familiar with SQL Injection a method to attack an application through holes in the way user input is
injected into SQL statements then dont worry. Under the hood, the sort string is parsed into an expression tree
which is eventually converted to the proper SQL statements in the same way as would occur with the lambda-based
versions of OrderBy and OrderByDescending. In other words, this does not open up your application to SQL Injection
attacks.
To install the DynamicQuery package, execute the following command in the Package Manager Console window:
Once the package is installed, you need the following using statement to bring the extension methods for sorting into
scope:
Now you can sort the list of contact people by passing in the proper sort and sortDir parameters as query string
values. You can find out more about this package at: http://nuget.org/packages/DynamicQuery.
Youll see the complete implementation of the Index method with sorting after I discussed paging.
Paging Data
Paging is another important feature for a web application. Trying to display hundreds or thousands or more records at
the same time will surely annoy your users and slow down your application. Fortunately, paging is easy using LINQs
Skip and Take methods.
Combining sorting and paging could give you the following Index method:
1 var sortedPeopleList = _peopleRepository.FindAll().OrderBy(x => x.DateOfBirth);
1
2
3
4
5
6
public ActionResult Index(string sort = "Id", string sortDir = "ASC")
{
var sortedPeopleList = _peopleRepository
.FindAll().OrderBy(string.Format("{0} {1}", sort, sortDir));
// Other code here
}
1 Install-Package DynamicQuery
1 using System.Linq.Dynamic;
1
2
3
4
5
6
public ActionResult Index(int page = 1, string sort = "Id", string sortDir = "ASC")
{
var allPeople = _peopleRepository.FindAll()
.OrderBy(string.Format("{0} {1}", sort, sortDir)).Skip((page * PageSize) - PageSize)
.Take(PageSize);
var model = new List<DisplayPerson>();
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 107 of 162
You can now pass in the requested page number (one-based) in a query string parameter called page. So, for
example, calling something like /People?page=2&sort=Id&sortDir=DESC would give you the second page of the
people list, with the records sorted in descending order based on their ID.
The Skip method skips ((page * PageSize) - PageSize) number of records. For page 1 with a page size of 10, that
would mean 0 (1x10 10 = 0). For the second page, it would skip 10 rows, giving you row 11 to 20, and so on. The
Take method then takes the requested number of items, defined by the PageSize constant. In a real world application,
you probably want to make the PageSize configurable, or even user-selectable, but for the sample the hardcoded
value works fine.
The final Index action method in the sample application looks slightly different. Heres its full code:
There are a few twists in this version. First, a count of all records is retrieved using Count(). This returns the total
number of people in the system, which is used in the view to build up the proper paging links. Next, the model is
different. Rather than just a list of DisplayPerson instances, the View Model now also contains a page number (the
currently displayed page), a page size, and the total number of rows. Heres how the PagerModel looks:
Notice that I made it generic, which means you can use it for other View Model types that need to support paging as
well.
The final piece of the puzzle is the view that displays the data. In the sample application, I chose to use the MVC
WebGrid as it ships with MVC. However, there are many other alternatives such as:
jQuery UI (http://jqueryui.com/)
Kendo UI (http://www.kendoui.com/ from Telerik)
DXTREME (http://www.devexpress.com/Products/HTML-JS/ from Dev Express)
The WebGrid code looks like this:
7
8
9
Mapper.Map(allPeople, model);
return View(model);
}
1
2
3
4
5
6
7
8
9
10
11
12
public ActionResult Index(int page = 1, string sort = "Id", string sortDir = "ASC")
{
int totalRecords = _peopleRepository.FindAll().Count();
var data = new List<DisplayPerson>();
IQueryable<Person> allPeople = _peopleRepository.FindAll()
.OrderBy(BuildOrderBy(sort, sortDir)).Skip((page * PageSize) - PageSize)
.Take(PageSize);
Mapper.Map(allPeople, data);
var model = new PagerModel<DisplayPerson>
{ Data = data, PageNumber = page, PageSize = PageSize, TotalRows = totalRecords };
return View(model);
}
1
2
3
4
5
6
7
public class PagerModel<T> where T: class
{
public IEnumerable<T> Data { get; set; }
public int PageSize { get; set; }
public int PageNumber {get; set;}
public int TotalRows {get; set;}
}
1
2
3
4
5
6
7
8
9
10
11
var grid = new WebGrid(null, defaultSort: "FirstName", columnNames:
new[] { "Id", "FullName", "DateOfBirth", "Type" }, rowsPerPage: Model.PageSize);
grid.Bind(Model.Data, rowCount: Model.TotalRows, autoSortAndPage: false);

@grid.GetHtml(columns: grid.Columns(
grid.Column("Id"),
grid.Column(header: "Full name", columnName: "FullName", format:
(item) => Html.ActionLink(((string)item.FullName), "Details", new { item.id })),
grid.Column("DateOfBirth", header: "Date of Birth", format:
(item) => item.DateOfBirth.ToString("d")),
grid.Column("Type", canSort: false),
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 108 of 162
Notice how I am passing the PageSize (from the View Model) to the constructor, and the actual data and number of
rows to the Bind method. The grid then uses that information to display the appropriate number of rows, as well as
paging links below the grid. The remainder of the code sets up the various columns for the persons ID, full name, date
of birth, and a bunch of links to edit addresses, e-mail addresses and phone numbers. This results in the following
screen:
(10) See Links in this Document at the end for the full URL of this image.
Figure 6-7 The List with Contact People
Most of the links in this screenshot are discussed in the remainder of this article.
If you run the sample application, youll notice you can click various headers to perform sorting. Most of them are
straightforward and sort directly on the property associated with the column. The exception is the FullName column.
Since that property only exists in the Model and is not present as a column in the database, sorting will fail. The
BuildOrderBy method in the PeopleController takes care of this as follows:
When the sortOn parameter equals fullname (which is what the WebGrid sends to the server when you click the Full
name column), sorting is done by combining the first name and the last name of the person. Obviously you can modify
this any way you want.
For a lot more background information on the MVC WebGrid, check out the following links:
http://msdn.microsoft.com/en-us/magazine/hh288075.aspx
http://weblogs.asp.net/andrebaltieri/archive/2010/11/01/asp-net-mvc-3-working-with-webgrid.aspx
http://weblogs.asp.net/andrebaltieri/archive/2010/11/02/asp-net-mvc-3-working-with-webgrid-part-2.aspx
12
13
14
15
16
17
18
19
20
21
22
23
grid.Column(header: "Addresses", format: item => new HtmlString(
Html.ActionLink("Home", "Edit", "Addresses", new { personId = item.Id,
contactType = (int)ContactType.Personal }, null).ToString() + " | " +
Html.ActionLink("Work", "Edit", "Addresses", new { personId = item.Id,
contactType = (int)ContactType.Business }, null).ToString())
),
grid.Column(format: (item) => Html.ActionLink("E-mail addresses", "List",
"EmailAddresses", new { personId = item.id }, null)),
grid.Column(format: (item) => Html.ActionLink("Phone numbers", "List", "PhoneNumbers",
new { personId = item.id }, null)),
grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { item.id })),
grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", new { item.id }))
1
2
3
4
5
6
7
8
private string BuildOrderBy(string sortOn, string sortDirection)
{
if (sortOn.ToLower() == "fullname")
{
return String.Format("FirstName {0}, LastName {0}", sortDirection);
}
return string.Format("{0} {1}", sortOn, sortDirection);
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 109 of 162
http://www.campusmvp.net/blog/webgrid-in-mvc-step-by-step-part-two
With the list of people done, its time to take a look at the Details action method.
Details
This method is executed when someone clicks a persons name in the grid. This requests /People/Details/personId
where personId is the ID of a person in the database. The action method is really simple, and it looks like this:
The method receives an ID of the person on the database which it uses to query the contact person from the
_peopleRepository using the FindById method. When that method returns null, the code returns an HttpNotFound
ActionResult which eventually results in a 404 Not Found error message in the client.
If the person does exist, its mapped to a DisplayPerson using AutoMapper and sent to the view where its displayed
using this code:
Because the Model type is a DisplayPerson, you can use all the properties of that class in the view. At the bottom
theres a simple action link that takes the user back to the list of people.
Create
In MVC, a Create action method usually has two versions: one that renders an empty form, and one that processes
the form after the user sends it back to the server. First, take a look at the action method that renders the view:
Action methods dont get any simpler than this. The view then looks as follows:
1
2
3
4
5
6
7
8
9
10
11
public ActionResult Details(int id)
{
Person person = _peopleRepository.FindById(id);
if (person == null)
{
return HttpNotFound();
}
var data = new DisplayPerson();
Mapper.Map(person, data);
return View(data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@model Spaanjaars.ContactManager45.Web.Mvc.Models.DisplayPerson
@{
ViewBag.Title = "Details";
}
<h2>@ViewBag.Title</h2>
<fieldset>
<legend>Person</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.FirstName)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.FirstName)
</div>

... Other fields go here

</fieldset>
<p>
@Html.ActionLink("Back to List", "Index")
</p>
1
2
3
4
public ActionResult Create()
{
return View();
}
1
2
3
@using Spaanjaars.ContactManager45.Web.Mvc.Helpers
@model Spaanjaars.ContactManager45.Web.Mvc.Models.CreateAndEditPerson
@{
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 110 of 162
All of this is standard MVC code so hopefully this looks familiar. Notice how the Model type in the view is set to
CreateAndEditPerson which I created specifically in the Models folder of the MVC project to create new and edit
existing people. Just as with the DisplayPerson, the code leaves out the complex properties of Person as they are
handled elsewhere:
Note: in the sample solution, the CreateAndEditPerson View Model implements the IValidatableObject interface to
enable complex validation capabilities. You see how this works later.
Notice how the properties have data annotation attributes applied to them. The DisplayName attribute influences the
name in the UI, so labels such as First name are displayed rather than FirstName. Youll see the required attributes
in the section on validation.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
ViewBag.Title = "Create new contact person";
}
<h2>@ViewBag.Title</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset>
<legend>Person</legend>

<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>

... Other fields go here

<div class="editor-label">
<label>Type</label>
@Html.ValidationMessageFor(model => model.Type)
</div>
<div class="editor-field">
@Html.EnumDropDownListFor(model => model.Type)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CreateAndEditPerson : IValidatableObject
{
public int Id { get; set; }

[Required, DisplayName("First name")]
public string FirstName { get; set; }

[Required, DisplayName("Last name")]
public string LastName { get; set; }

[DisplayName("Date of birth")]
public DateTime DateOfBirth { get; set; }

public PersonType Type { get; set; }

// Validation code here
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 111 of 162
Just as with DisplayPerson, you need a mapping in AutoMapper, but this time in both directions. You need to map
from CreateAndEditPerson to a Person in the Create action method when the form is submitted to the server.
Mapping in the opposite direction is done by the Edit method as youll see in a bit.
Your first attempt at the mapping code might look like this:
However, if you were to run this, AssertConfigurationIsValid would signal the following exception:
(11) See Links in this Document at the end for the full URL of this image.
Figure 6-8 An AutoMapper Exception Pointing out Issues with the Mapping Configuration
What this error message tells you is that the source type (CreateAndEditPerson) does not supply a value for the six
properties listed. In this case, this is exactly what you want. The two date properties are set by EF automatically when
saving the entity, and the four contact details are managed elsewhere. You can let AutoMapper know youre fine with
this using the Ignore method, like this:
Notice how the Ignore method is used to indicate you really want these properties ignored. You dont have to specify
these for the reverse mapping because CreateAndEditPerson doesnt have any properties that Person doesnt have.
With all of this set up, handling the Create action method is now pretty straight forward:
1
2
Mapper.CreateMap<CreateAndEditPerson, Person>();
Mapper.CreateMap<Person, CreateAndEditPerson>();
1
2
3
4
5
6
7
Mapper.CreateMap<CreateAndEditPerson, Person>()
.ForMember(d => d.DateCreated, t => t.Ignore())
.ForMember(d => d.DateModified, t => t.Ignore())
.ForMember(d => d.EmailAddresses, t => t.Ignore())
.ForMember(d => d.PhoneNumbers, t => t.Ignore())
.ForMember(d => d.HomeAddress, t => t.Ignore())
.ForMember(d => d.WorkAddress, t => t.Ignore());
1
2
3
4
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateAndEditPerson createAndEditPerson)
{
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 112 of 162
Based on the Model type of the Create view, the model binder in ASP.NET MVC constructs a CreateAndEditPerson
instance for you and fills it with the data from the form. If the object is considered valid (e.g. the Required attributes
and other validation rules in that View Model are satisfied), the model is mapped to a Person from the Model project
and added to the data context using the repositorys Add method. Since the code is wrapped in a using block that
creates a unit of work, the changes are saved automatically at the end of the code block.
If updating the database fails, the data context throws a ModelValidationException with the validation errors in its
ValidationErrors property. You saw how the data context created and filled the exception in Part 5 that discussed
ways to improve the error messages from the data context. Here, I am using those messages to load them in the
ModelState so they nicely show up in the UI, even though they are raised somewhere deep down in the EF data layer.
With Create covered, Edit is now pretty easy as it follows the same pattern.
Edit
Edit also consists of two action methods: one for GET and one for POST. Heres the GET version:
Hopefully, this is easy code by now. A Person is retrieved from the database using the PeopleRepository. Its then
mapped into a CreateAndEditPerson View Model and sent off to the view. That view is almost the same as the one for
create, except for the field for the ID of the person being edited. Rather than creating two separate, but almost
identical views, you can use partial views and extract the part of the views that is the same to a separate view file and
reference that from the Create and Edit views. This is the route I have taken for the e-mail addresses and phone
numbers (and which the tooling in Visual Studio creates by default), so check out those views if you want to learn
more.
On postback, the following Edit method to save the contact person in the database is executed:
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if (ModelState.IsValid)
{
try
{
using (_unitOfWorkFactory.Create())
{
Person person = new Person();
Mapper.Map(createAndEditPerson, person);
_peopleRepository.Add(person);
return RedirectToAction("Index");
}
}
catch (ModelValidationException mvex)
{
foreach (var error in mvex.ValidationErrors)
{
ModelState.AddModelError(
error.MemberNames.FirstOrDefault() ?? "", error.ErrorMessage);
}
}
}
return View();
}
1
2
3
4
5
6
7
8
9
10
11
public ActionResult Edit(int id)
{
Person person = _peopleRepository.FindById(id);
if (person == null)
{
return HttpNotFound();
}
var data = new CreateAndEditPerson();
Mapper.Map(person, data);
return View(data);
}
1
2
3
4
5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CreateAndEditPerson createAndEditPerson)
{
if (ModelState.IsValid)
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 113 of 162
This is almost the same code as the POST version of the Create method. Here, an existing person is retrieved from
the database and then updated with the values from the submitted View Model. In this case, I had to explicitly pass
the source and target types to the Map method. The reason for this is that although the personToUpdate looks like a
plain Person instance, its actually a class derived from it. EF has created this so-called dynamic-proxy type to enable
features such as lazy loading. Without the explicitly defined types, AutoMapper will complain there is no mapping
between the dynamically created proxy and the CreateAndEditPerson class. More info about this can be found here:
http://stackoverflow.com/questions/13416816/how-to-update-an-existing-entity-from-viewmodel-using-automapper-
and-ef4-dbconte
The final action method in the PersonController is Delete, discussed next.
Delete
Delete also consists of a GET and a POST version. Heres the code for both:
In the GET version, I retrieve the person from the database and convert it into a DisplayPerson. This is useful if you
want to show a confirmation screen that lists the details of the entity youre about to delete.
In the POST version, the ID of the person is submitted which is then fed into the Remove method of the
PeopleRepository. This deletes the person from the database, as well as its related contact data such as phone
numbers and email records. The changes are saved automatically as the code is wrapped in a using block that creates
a unit of work.
Handling Validation
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
try
{
using (_unitOfWorkFactory.Create())
{
Person personToUpdate = _peopleRepository.FindById(createAndEditPerson.Id);
Mapper.Map(createAndEditPerson, personToUpdate, typeof(CreateAndEditPerson),
typeof(Person));
return RedirectToAction("Index");
}
}
catch (ModelValidationException mvex)
{
foreach (var error in mvex.ValidationErrors)
{
ModelState.AddModelError(error.MemberNames.FirstOrDefault() ?? "", error.ErrorMessage);
}
}
}
return View();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public ActionResult Delete(int id)
{
Person person = _peopleRepository.FindById(id);
if (person == null)
{
return HttpNotFound();
}
var data = new DisplayPerson();
Mapper.Map(person, data);
return View(data);
}

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
using (_unitOfWorkFactory.Create())
{
_peopleRepository.Remove(id);
}
return RedirectToAction("Index");
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 114 of 162
Although youve already seen some validation at work, I want to briefly list a few important implementation details.
First, take a look at the full code for the CreateAndEditPerson class:
Depending on how you look at things, there may be some stuff you dont like. For example, the Validate method
seems like a replication of a part of the Validate method in the Person class (and it is.) Also, the Required attributes
seem duplicated between Person and its CreateAndEditPerson View Model. This is a consequence of the separation
using the View Models; if you were using a Person directly, you could directly access its Validate method. In my
opinion, the benefits of using separate View Models outweigh any issues associated with it, so I dont mind duplicating
some of the validation. In fact, it turns out that sometimes I have different validation rules in my view model than in
my model. For example, when working with a legacy database, the model could have relaxed validation to let old data
go in and out without a problem. However, new data entered through an ASP.NET MVC UI needs to stick to stricter
rules. This is easily accomplished with a separate View Model for Create and Edit, each with their own validation rules.
Note: the validation at the model level is carried out as well when the entities are saved to the database. This means
that View Models never jeopardize the quality of your data; your model always stays in control and has a final say
about the data.
In the EditAddress view model that is used to edit Address instances (there is only an Edit model as you cant create
new addresses in the UI), I avoided duplication of validation code by leveraging the Validate method of the
associated Address class, like this:
This way, you dont need to duplicate any code; you just ask Address if it can make a valid instance out of the fields
passed to it, and use that to validate the EditAddress instance. I left both concepts in the sample application as I find
theres room for both options.
Youre encouraged to look at the other controllers in the application, along with their View Models and views. Although
the implementation is slightly different here and there, a lot of the code is based on the same principles that youve
just seen.
The final topic that needs to be discussed is how the application is able to display nice drop-down lists based on the
various enums in the application. Youll see how this is done next.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class CreateAndEditPerson : IValidatableObject
{
public int Id { get; set; }
[Required, DisplayName("First name")]
public string FirstName { get; set; }
[Required, DisplayName("Last name")]
public string LastName { get; set; }
[DisplayName("Date of birth")]
public DateTime DateOfBirth { get; set; }
public PersonType Type { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Type == PersonType.None)
{
yield return new ValidationResult("PersonType can't be None", new[] { "Type" });
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class EditAddress : IValidatableObject
{
public int PersonId { get; set; }
public string Street { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public ContactType { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return new Address(Street, City, ZipCode, Country, ContactType).Validate();
}
}
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 115 of 162
Implementing Drop Down Lists
You may have noticed that when you add a contact person, you get a nice drop-down to select a type:
Figure 6-9 A Drop-Down List with Values from an Enum
Neither ASP.NET nor MVC have built in support for converting enums to a drop down list. However, its quite easy to
implement.
When you look at the Create or Edit view for a Person, you see something like this:
A nice and clean implementation using an extension method, as the EnumDropDownListFor method is able to infer the
underlying enum type to build the drop down, and use the models value to preselect the current value if it exists.
The implementation of EnumDropDownListFor is based on a few articles I found on the Internet, where the following
one looked like the most complete and stable implementation:
http://www.jonegerton.com/dotnet/dropdownlist-helper-for-enums/. For more background, and a way to localize these
drop-downs, check out these resources:
http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-
for-enums.aspx
http://stackoverflow.com/questions/4656758/mvc3-razor-dropdownlistfor-enums/4
http://ruijarimba.wordpress.com/2012/02/17/asp-net-mvc-creating-localized-dropdownlists-for-enums/
In my implementation I added the SplitString method (and renamed it to PascalCaseToSpaces) as suggested by
Nick in the blog post from Stuart Leeks to change PascalCasedEnumItems to a version with spaces (Pascal Cased
Enum Items) in the drop-down list.
Stuff I Like to Do
Implement a BaseController. Although certainly not required, I find it useful if all my controllers inherit a
common and custom base controller (called BaseController in the sample project). This makes it easy at any
stage of the application to add behavior to all controllers at once.
Call Mapper.AssertConfigurationIsValid at the end of your AutoMapper configuration code to ensure all
mappings are valid. Without that call, you code appears to run fine, but you may run into problems later when
the faulty mapping is used in your code.
Give your View Models logical names so you can easily find them. I typically use a naming convention like
action followed by the type (such as ListPerson to display people in a list) or something like DisplayType,
CreateType, EditType or CreateAndEditType, to indicate what they are used for.
Although not shown in this project, its easy (and recommended) to use UI frameworks like jQuery UI or Kendo
UI. These frameworks make it easy to create good-looking UIs with little effort.
Summary
In this article you saw how to use the model and repositories developed in earlier parts in the series for an ASP.NET
MVC 4 application. In particular, you saw how to use a dependency framework to inject concrete instances of the
IPeopleRepository and IUnitOfWork interfaces into the controllers of the project. A good part of the article was then
spent discussing the implementation of the PeopleRepository and its methods to implement CRUD (Create, Read,
Update and Delete) operations. At the end of the article, you saw how validation is handled and how enums are used
to create better looking drop-down lists via extension methods.
In the next article youll see how to implement the same frontend UI, this time using ASP.NET 4.5 Web Forms.
1 @Html.EnumDropDownListFor(model => model.Type)
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 116 of 162
Links in this Document
(1) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-1_MVC_People_list.png
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-2_MVC_Edit_Person.png
(3) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-3_MVC_Edit_Address.png
(4) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-4_MVC_EmailAddresses.png
(5) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-5_Model_Architecture.png
(6) http://www.manning.com/seemann/
(7) http://docs.structuremap.net/
(8) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-6_Architecture_Diagram.png
(9) http://automapper.org/
(10) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-7_People_list.png
(11) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part06/Figure6-8_AutoMapper_Exception.png
ASP.NET N-Layered Applications - Implementing an ASP.NET MVC 4 Frontend (Part 6)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 117 of 162
ASP.NET N-Layered Applications - Implementing a Web Forms
4.5 Frontend (Part 7)
This is Part 7 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a Web UI using ASP.NET Web Forms and make use of the
model and repository projects I have shown in the first five articles in this series.
Introduction
ASP.NET Web Forms has been around for a long time (since early 2002), and its the framework of choice for a large
number of developers around the world. Partially modeled after desktop applications, ASP.NET Web Forms applications
are event driven and use a post back model where each (or at least most) pages post back to themselves.
In this article, Ill show you how to use the repository and models created in the earlier parts of this series in an
ASP.NET Web Forms application. Ill cover the following topics:
How to use the new Model Binding capabilities of ASP.NET 4.5 to access a repository.
How to use the validation functionality of the model in the UI.
How to use the Unit of Work pattern to save changes to the database as a batch.
How to centralize creation of the repository and unit of work instances as an alternative to dependency
injection you saw in Part 6.
This article is not meant as an introduction to ASP.NET Web Forms. If youre new to Web Forms, I recommend checking
out the following resources:
Getting Started with Web Forms (http://www.asp.net/web-forms/overview/getting-started)
My book Beginning ASP.NET 4.5 in C# and VB (Wrox, 2012) - http://www.amazon.com/Beginning-ASP-NET-
4-5-C-VB/dp/1118311809/
Professional ASP.NET 4.5 in C# and VB (Gaylord et. al. Wrox, 2013) - http://www.amazon.com/Professional-
ASP-NET-4-5-C-VB/dp/1118311825/
In Part 2 of this article series you saw how to add the Web Forms project to the solution. I used the ASP.NET Web
Forms Application template as the starting point which gives you a bunch of pages, a master file and some content
files that define the global look and feel of the site. To make it easy to see whats going on, I havent changed much in
the original layout files that ship with a new ASP.NET Web Forms project. I made a few minor changes to align the
design with the one from the ASP.NET MVC sample application, but thats it. If youre familiar with the ASP.NET Web
Forms standard project, youll feel right at home.
In Part 1, Ive provided a brief overview of the sample application and showed you a few screenshots. Heres a brief
recap of what the application can do. Remember: the purpose of this article series and this demo web site is to show
you how to design an application from an architecture point of view. The demo does not feature a complete feature set
(such as a fancy UI) as you would normally build in real-world web sites.
NOTE: these screenshots are similar to the ones from the article about ASP.NET MVC. I implemented the exact same
functionality in both applications so you can see how to make use of the repositories in each application type.
When you start up the application you see the home screen with a short welcome text. When you click the People
menu, you see all the contact people in the system with links to edit and delete them, and to manage their contact
data:
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 118 of 162
(1) See Links in this Document at the end for the full URL of this image.
Figure 7-1 The Web Forms Site Showing all Contact People
When you click Edit for a contact person, you see the following page:
(2) See Links in this Document at the end for the full URL of this image.
Figure 7-2 Editing a Single Contact Person
When you click one of the address links on the main People page (shown in Figure 7-1), you see a screen that lets you
manage address details. In this case, the user already pressed the Save button and the validation (from the Address
class in the Model project) kicked in:
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 119 of 162
(3) See Links in this Document at the end for the full URL of this image.
Figure 7-3 Validation at Work when Editing an Address
When you click the Email addresses or Phone numbers link in the main list of People (shown in Figure 7-1), you see a
list of associated contact records for that person:
(4) See Links in this Document at the end for the full URL of this image.
Figure 7-4 Managing E-mail Addresses
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 120 of 162
From here, you can manage the existing data (edit and delete) as well as create new e-mail addresses for this user.
The About page provides more background on the application and the Contact page can be used to get in touch with
me. The Register and Login links at the top come from the standard Web Forms template. They are fully functional,
but not used in the sample application.
Under the hood, this Web Forms application uses the PeopleRepository targeting the Entity Framework for all data
access. The list of people is retrieved using FindAll, a details page uses FindById, the insert pages use Add, and so
on. To see how it all fits together, heres the architecture diagram showing the Web Forms frontend application and
how its related to the other components in the system:
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 121 of 162
(5) See Links in this Document at the end for the full URL of this image.
Figure 7-5 The Architecture Diagram
Since its pretty difficult today to unit test your ASP.NET Web Forms pages, I wont attempt to decouple the Entity
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 122 of 162
Framework based versions of the PeopleRepository and UnitOfWork and the Web Forms. However, I will centralize
the creation of these classes using a factory method so you only have one place where these classes are instantiated.
This makes it easy to use another repository implementation if you choose so.
Ill use the new Model Binding capabilities introduced in ASP.NET 4.5 for all my data access as youll see in the next
section.
Building the Pages to Manage Contact People and Related Data
If youve worked with model binding in ASP.NET 4.5 Web Forms before, the following sections will look very familiar to
you. If youre new to model binding, be sure to check out the following resources first:
http://blogs.msdn.com/b/webdev/archive/2013/03/28/tutorial-series-on-model-binding-with-asp-net-web-
forms.aspx
http://www.codeguru.com/csharp/.net/net_asp/controls/using-model-binding-in-asp.net-data-controls.htm
With model binding, you dont use the traditional data source controls to get data from a database and hand it over to
a data-bound control. Instead, you create one or more methods to handle CRUD operations in your code behind, and
then link your data-bound control to these methods using properties of the control. Heres the markup of a rather
simplified example that displays people in a GridView and lets you edit them:
Notice how the GridView and DetailsView together have four methods configured to support all CRUD operations:
SelectMethod, UpdateMethod, DeleteMethod and InsertMethod.
These four methods are configured in the code behind and could look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<asp:GridView ID="GridView1" runat="server" DataKeyNames="Id"
ItemType="Spaanjaars.ContactManager45.Model.Person" SelectMethod="FindAll"
UpdateMethod="UpdatePerson" DeleteMethod="DeletePerson">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
</Columns>
</asp:GridView>
<asp:DetailsView ID="DetailsView1" runat="server"
ItemType="Spaanjaars.ContactManager45.Model.Person" SelectMethod="FindAll"
InsertMethod="InsertPerson" DefaultMode="Insert">
<Fields>
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public IEnumerable<Person> FindAll()
{
return RepositoryHelpers.GetPeopleRepository().FindAll();
}

public void InsertPerson()
{
var person = new Person();
TryUpdateModel(person);
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
RepositoryHelpers.GetPeopleRepository().Add(person);
}
}

public void UpdatePerson(int id)
{
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
var person = RepositoryHelpers.GetPeopleRepository().FindById(id);
TryUpdateModel(person);
}
}

public void DeletePerson(int id)
{
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 123 of 162
Each method works with the PeopleRepositiory (retrieved from the RepositoryHelpers class which youll see
shortly) to get data from the database, and send changes back.
Note: this code serves only as an example; its missing some real-world validation and exception handling (although
the model still takes care of the validation before entities are saved to the database) so you shouldnt use this as-is.
Instead, read on to see how to improve the situation with only a minimum amount of code.
The Web Forms project contains a People folder that has web forms to manage contact people and their associated
contact details. Figure 7-6 shows the Solution Explorer for the project:
Figure 7-6 Solution Explorer for the Web Forms project
Ill discuss the files in this folder in the next few sections.
List
As you saw at the beginning of the article, the applications main page has a list of all the contact people in the
system. The list is shown using the following code (inside /People/Default.aspx):
29
30
31
RepositoryHelpers.GetPeopleRepository().Remove(id);
}
}
1
2
3
<asp:GridView ID="categoriesGrid" runat="server" AutoGenerateColumns="false"
AllowSorting="true" AllowPaging="true" PageSize="10"
ItemType="Spaanjaars.ContactManager45.Model.Person"
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 124 of 162
There are a few important details in this code. First, the GridView is set up to get its data using ListPeople in its
SelectMethod attribute. Likewise, DeletePerson will be called whenever a contact person needs to be deleted.
Furthermore, the GridView is set up to use sorting and paging by the attributes AllowSorting and AllowPaging.
Since the SelectMethod returns an IQueryable<T>, the control is able to figure how to do (efficient) paging and
sorting, by executing the correct Skip, Take and OrderBy methods for you.
Note the attribute ItemType that is set to Spaanjaars.ContactManager45.Model.Person. This attribute is also new in
ASP.NET 4.5 and enables you to strongly type your GridView to a specific model type. This allows you to do cool stuff
like this:
Notice how this code refers to Item.Id to append the ID of the contact person to the navigation URL. Youll get full
IntelliSense support because Item in this example is a real Person type. This makes it a lot easier to configure
your controls and make fewer mistakes. Item has BindItem as its counterpart for insert and update behavior as youll
see later.
In the code behind, you find the ListPeople method that looks like this:
This code retrieves a PeopleRepository from the RepositoryHelpers class. It then calls FindAll followed by a call to
OrderBy to do an initial sort of the data. This is required because Entity Framework doesnt support calling Skip and
Take (which is what the GridView will call to support paging) on an unsorted set of data. The RepositoryHelpers is
another poor mens implementation of Dependency Injection and its code looks like this:
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
SelectMethod="ListPeople" DeleteMethod="DeletePerson" GridLines="None"
CellSpacing="5" EmptyDataText="No contact people found.">
<Columns>
<asp:BoundField DataField="Id" HeaderText="ID" SortExpression="Id" />
<asp:HyperLinkField DataNavigateUrlFields="Id" HeaderText="Full name"
SortExpression="FirstName" DataNavigateUrlFormatString="Details.aspx?Id={0}"
DataTextField="FullName"></asp:HyperLinkField>
<asp:BoundField DataField="DateOfBirth" HeaderText="Date of Birth"
SortExpression="DateOfBirth" DataFormatString="{0:d}" />
<asp:BoundField DataField="Type" HeaderText="Type" SortExpression="Type" />
<asp:TemplateField HeaderText="Addresses">
<ItemTemplate>
<asp:HyperLink runat="server" NavigateUrl='
<%# string.Format("EditAddress.aspx?Id={0}&ContactType=2", Item.Id) %>' Text="Home">
</asp:HyperLink>
|
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='
<%# string.Format("EditAddress.aspx?Id={0}&ContactType=1", Item.Id) %>' Text="Work">
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:HyperLinkField DataNavigateUrlFields="Id" HeaderText=""
DataNavigateUrlFormatString="EmailAddresses.aspx?Id={0}" Text="E-mail addresses">
</asp:HyperLinkField>
<asp:HyperLinkField DataNavigateUrlFields="Id" HeaderText=""
DataNavigateUrlFormatString="PhoneNumbers.aspx?Id={0}" Text="Phone numbers">
</asp:HyperLinkField>
<asp:HyperLinkField DataNavigateUrlFields="Id" HeaderText=""
DataNavigateUrlFormatString="AddEditPerson.aspx?Id={0}" Text="Edit">
</asp:HyperLinkField>
<asp:CommandField ShowDeleteButton="True" />
</Columns>
</asp:GridView>
1
2
3
<asp:HyperLink runat="server" NavigateUrl='
<%# string.Format("EditAddress.aspx?Id={0}&ContactType=2", Item.Id) %>' Text="Home">
</asp:HyperLink>
1
2
3
4
5
public IQueryable<Person> ListPeople()
{
var repo = RepositoryHelpers.GetPeopleRepository();
return repo.FindAll().OrderBy(x => x.Id);
}
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 125 of 162
I wrote this class to abstract the creation of instances of the IPeopleRepository and IUnitOfWorkFactory interfaces.
The calling code (my ASPX pages) doesnt know of the existence of concrete implementations like PeopleRepository
in the EF project. All it needs to understand is the IPeopleRepository abstraction. This makes it easy to swap your EF
PeopleRepository for another one (using NHibernate or some other data access technology): just reference the new
type, change the type returned from the two methods inside the RepositoryHelpers class, and youre done.
Since deleting entities is done in the same page, Ill discuss that next.
Delete
For the GridView to support deleting using your repositories, all you need is a DeleteMethod in the code behind and a
CommandField with its ShowDeleteButton property set to true. Then when you click the Delete link for an entity in the
GridView, this code in the Code Behind is executed:
The GridView automatically passes the persons ID to the method so deleting the entity is as simple as creating an
instance of UnitOfWork, and then calling Remove on the PersonRepository.
If you look at the code for the GridView you see that the Full Name column links to a Details page. This page is
discussed next.
Details
The frontend part of Details.aspx is pretty simple. I used an old skool <table> element to present some details of
the person. Heres an example of the row that shows the last name:
In code behind, these controls are given a value with this code:
1
2
3
4
5
6
7
8
9
10
11
12
public static class RepositoryHelpers
{
public static IPeopleRepository GetPeopleRepository()
{
return new PeopleRepository();
}

public static IUnitOfWorkFactory GetUnitOfWorkFactory()
{
return new EFUnitOfWorkFactory();
}
}
1
2
3
4
5
6
7
public void DeletePerson(int id)
{
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
RepositoryHelpers.GetPeopleRepository().Remove(id);
}
}
1
2
3
4
5
6
<tr>
<td>Last name</td>
<td>
<asp:Label ID="LastName" runat="server"></asp:Label>
</td>
</tr>
1
2
3
4
5
6
7
8
9
10
11
12
public partial class Details : System.Web.UI.Page
{
private int _personId;
protected void Page_Load(object sender, EventArgs e)
{
string personIdAsString = Request.QueryString.Get("Id");
if (string.IsNullOrEmpty(personIdAsString) || !int.TryParse(personIdAsString, out _personId))
{
Response.Redirect("~/");
}
LoadPerson();
}
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 126 of 162
The code in Page_Load ensures there is an ID for a person in the Query String and that it can be converted to an
integer. If either condition fails, the user is sent back to the root of the site.
In the LoadPerson method, the code accesses the RepositoryHelpers to get a repository and then uses the familiar
FindById method to find the requested person. If the person is found, its properties are used to populate the various
controls on the page.
Theres no action for the situation where the person is not found, but its easy to add. Depending on your
requirements, you could redirect to the list of people page, show an error page, or simply tell the user you cant find
the requested person by updating a Label or so. In the last case, you also want to send out a HTTP 404 (not found)
error code to tell search engines to stop indexing the page:
With the list and details pages done, the next step is creating and editing contact people.
Create, Edit and Building DropDownList Controls from Enums
To create contact people, I chose a different implementation than for the contact records. For the contact people, I
chose a concept I refer to as hand coding data access. It comes down to a bunch of regular input controls (text
boxes, drop down lists etc.) whose values are used to fill an instance of, in this case, a Person. I prefer this solution
over data-bound controls such as the DetailsView for complex pages. Rather than messing with the various insert
and edit templates, you can have a single page that handles both. In the case of the contact manager, the page
AddEditPerson.aspx looks like this:
13
14
15
16
17
18
19
20
21
22
23
24
25
26

private void LoadPerson()
{
var peopleRepository = RepositoryHelpers.GetPeopleRepository();
var person = peopleRepository.FindById(_personId);
if (person != null)
{
FirstName.Text = person.FirstName;
LastName.Text = person.LastName;
DateOfBirth.Text = person.DateOfBirth.ToString("d");
Type.Text = person.Type.ToString();
}
}
}
1
2
3
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.TrySkipIisCustomErrors = true;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ Page Title="ContactManager" Language="C#" MasterPageFile="~/Site.Master"
AutoEventWireup="true" CodeBehind="AddEditPerson.aspx.cs"
Inherits="Spaanjaars.ContactManager45.Web.WebForms.People.AddEditPerson" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
<style type="text/css">
.auto-style1 {
width: 100%;
}
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<table class="auto-style1">
<tr>
<td>First name</td>
<td>
<asp:TextBox ID="FirstName" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>Last name</td>
<td>
<asp:TextBox ID="LastName" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 127 of 162
This is pretty standard ASP.NET code: a table for layout (again, an old skool solution but fine for this demo) with
standard ASP.NET controls. At the bottom of the table you see a DropDownList with a SelectMethod called GetTypes
which youll see in a minute. The ValidationSummary at the end is used to show model errors that may occur when
saving an entity.
In the Code Behind, Page_Load has the same defensive code as Details.aspx. However, this time its OK when no ID
is passed to the page, as that means the page is used to create a new Person instead of editing an existing one. When
theres an ID, LoadPerson gets the person and fills the controls like this:
This is more or less the same as in the details page, except for the code that selects the persons Type. In order to
ensure the DropDownList for the type has all its items, the code first calls the DataBind method on the DropDownList
for the Type property. This forces it to call the GetTypes method that looks like this:
The EnumToListItems method looks like this:
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<td>Date of birth</td>
<td>
<asp:TextBox ID="DateOfBirth" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>Type</td>
<td>
<asp:DropDownList ID="Type" runat="server" SelectMethod="GetTypes"
DataValueField="Value" DataTextField="Text">
</asp:DropDownList>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Save" />
<a href="Default.aspx">Back to List</a></td>
</tr>
</table>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" ForeColor="Red"
ShowModelStateErrors="true" HeaderText="Please check the following errors:" />
</asp:Content>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void LoadPerson()
{
var peopleRepository = RepositoryHelpers.GetPeopleRepository();
var person = peopleRepository.FindById(_personId);
if (person != null)
{
FirstName.Text = person.FirstName;
LastName.Text = person.LastName;
DateOfBirth.Text = person.DateOfBirth.ToString("d");
Type.DataBind();
var item = Type.Items.FindByValue(((int)person.Type).ToString());
if (item != null)
{
item.Selected = true;
}
}
}
1
2
3
4
public IEnumerable<ListItem> GetTypes()
{
return Helpers.EnumToListItems<PersonType>();
}
1
2
3
4
5
internal static IEnumerable<ListItem> EnumToListItems<T>()
{
Type type = typeof(T);
var result = new List<ListItem>();
var values = Enum.GetValues(type);
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 128 of 162
I have taken a slightly simpler approach than in the ASP.NET MVC version of the site. The code gets the type of the
generic T parameter and feeds it into Enum.GetValues. This returns an array with the available options that the code
loops over. I used the PascalCaseToSpaces method again to split and pascal case values and add spaces. I duplicated
that code in both projects. In a real-world project, I would probably add another class library to the project, called
Spaanjaars.Toolkit for example, move all this shared code into that project and then reference it from both UI
projects.
When the Save button is clicked, the following code is executed:
This code gets an existing person or creates a new one and adds it to the underlying data context using the
repositorys Add method. It then gets the values from the controls and assigns them to the properties of the Person
instance.
In this example, I am relying on model validation completely. So, only when EF rejects the values does the code show
errors to the user. If you wanted to, you could call Validate on the Person and manually add validation errors to the
ModelState object. You would need to do this outside the unit of work to avoid the changes being submitted to the
database even though you know they are valid. Alternatively, you could call the Undo method on the unit of work to
cancel all open changes.
The Create and Edit pages for e-mail addresses and phone numbers are implemented differently. Because the data is
quite simple, I used the standard data-bound controls along with model binding. (Note: I could just as easily have
applied the same principles as used for the AddEditPerson.aspx page; but I chose the built-in data controls to show
you different ways to implement data-driven pages).
6
7
8
9
10
11
12
13

foreach (int value in values)
{
string text = Enum.GetName(type, value);
result.Add(new ListItem(text, value.ToString().PascalCaseToSpaces()));
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
protected void SaveButton_Click(object sender, EventArgs e)
{
try
{
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
var repository = RepositoryHelpers.GetPeopleRepository();
Person person;
if (_personId == 0)
{
person = new Person();
repository.Add(person);
}
else
{
person = repository.FindById(_personId);
}

person.FirstName = FirstName.Text;
person.LastName = LastName.Text;
person.DateOfBirth = Convert.ToDateTime(DateOfBirth.Text);
person.Type = (PersonType)Enum.Parse(typeof(PersonType), Type.SelectedValue);
}
Response.Redirect("Default.aspx");
}
catch (ModelValidationException mvex)
{
foreach (var error in mvex.ValidationErrors)
{
ModelState.AddModelError(error.MemberNames.FirstOrDefault() ?? "",
error.ErrorMessage);
}
}
}
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 129 of 162
As an example, take a look at the InsertPhoneNumber method in the Code Behind of PhoneNumbers.aspx:
Although the phoneNumber parameter in the method isnt used in the code, its important to have it there. Without it,
model validation isnt triggered and ModelState.IsValid returns true. With the parameter there, the model binder
fills in the values coming from the form which in turn updates the IsValid state. So, if you omit the number or the
type, the code in the if block wont attempt to add the phone number to the users PhoneNumbers collection and
shows the validation errors to the user with the ValidationSummary control. An alternative solution is to remove the
parameter from the methods signature and then rely on TryUpdateModel to set the value for IsValid. In this case,
its important to carry out this check before you enter the using block of the unit of work or call the Undo method,
otherwise the unit of work will still try to apply your changes.
The code also uses a try/catch block to catch and display any validation exceptions that may have been triggered by
the EF data context.
Most of this code is pretty straightforward and similar to how you would do it without a repository and regular model
binding. Theres one area that needs a bit more attention though: handling the enums in the GridView. To implement
enum support in the GridView, you need the following steps:
Create a TemplateField in the GridView for the ContactType. 1.
Inside the ItemTemplate, write out the text representation of the enum. 2.
Inside the EditItemTemplate, create a DropDownList control that shows the available options and preselects
the correct item
3.
When the item is being saved, retrieve the value from the DropDownList and assign it to the item. 4.
Youll find the details of these steps in the next sections:
Create a TemplateField in the GridView for the ContactType.
This is simple to do: just remove the BoundField for the ContactType property and replace it with something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void InsertPhoneNumber([QueryString("Id")] int personId, PhoneNumber phoneNumber)
{
if (ModelState.IsValid)
{
try
{
using (RepositoryHelpers.GetUnitOfWorkFactory().Create())
{
var repo = RepositoryHelpers.GetPeopleRepository();
var person = repo.FindById(personId, x => x.PhoneNumbers);
var userNumber = new PhoneNumber { OwnerId = personId };
TryUpdateModel(userNumber);
person.PhoneNumbers.Add(userNumber);
}
}
catch (ModelValidationException mvex)
{
foreach (var error in mvex.ValidationErrors)
{
ModelState.AddModelError(error.MemberNames.FirstOrDefault() ?? "",
error.ErrorMessage);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
<asp:GridView ID="PhoneNumbersGrid" runat="server" AutoGenerateColumns="False"
... Other code here. OnRowUpdating is used in step 4.
OnRowUpdating="PhoneNumbersGrid_RowUpdating">
<Columns>
<asp:BoundField DataField="Id" HeaderText="ID" SortExpression="Id" ReadOnly="True" />
... Other fields here

<asp:TemplateField HeaderText="ContactType" SortExpression="ContactType">

... templates go here

</asp:TemplateField>
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 130 of 162
Inside the ItemTemplate, Write Out the Text Representation of the Enum.
Inside the ItemTemplate, you can display the ContactType for an e-mail address with a Label. The following code
does the trick:
When called, this displays the string representation of the enum, so it would display something like Personal or
Business.
Inside the EditItemTemplate, Create a Drop-Down lList
The EditItemTemplate is a little trickier. When using plain integer values you would probably do something like this:
Unfortunately, this doesnt work. The enum has a value (such as 0, 1, 2) which is different from the text that gets
displayed. In the example above, the code would try to preselect an item by its text (like Personal) rather than by its
value. My next attempt was to cast the value to an int. However, that means you can no longer use BindItem. For
BindItem to work in two directions (to display and to edit a value) you need to use BindItem as-is. The final solution I
came up with is this:
Notice how I am using Item rather than BindItem. Item is only used to display the value and does not try to bind the
value again when the item is being edited. The cast to an int then ensures that the numeric value of the ContactType
is returned which is exactly whats needed to preselect the item in the DropDownList control. The effect of this is that
the GridView is no longer able to use this data after a postback when the item needs to be changed. However, its
easy to manually do this as you see next.
When the item is being saved, retrieve the value from the DropDownList and assign it to the item.
When the GridView is about to call the Update method, it fires its Updating event first. You can hook into this event,
find the selected value of the ContactType DropDownList and assign it to the NewValues collection like this:
The value you assign to the NewValues collection carries over to the data in the model binder, so by the time
UpdateEmailAddress gets called, this value is available and assigned to the e-mail address that is about to be saved in
the database.
13
14
15
16

... Other fields here
</Columns>
</asp:GridView>
1
2
3
4
5
<asp:TemplateField HeaderText="ContactType" SortExpression="ContactType">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("ContactType") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
1
2
3
4
5
6
<EditItemTemplate>
<asp:DropDownList runat="server" ID="ContactType"
SelectedValue='<%# BindItem.ContactType) %>' SelectMethod="GetContactTypes"
DataValueField="Value" DataTextField="Text">
</asp:DropDownList>
</EditItemTemplate>
1
2
3
4
5
6
<EditItemTemplate>
<asp:DropDownList runat="server" ID="ContactType"
SelectedValue='<%# (int)(Item.ContactType) %>'
SelectMethod="GetContactTypes" DataValueField="Value"
DataTextField="Text"></asp:DropDownList>
</EditItemTemplate>
1
2
3
4
5
6
protected void EmailAddressesGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
var typeDropDown = (DropDownList)
EmailAddressesGrid.Rows[e.RowIndex].FindControl("ContactType");
e.NewValues["ContactType"] = (ContactType)Convert.ToInt32(typeDropDown.SelectedValue);
}
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 131 of 162
This concludes the implementation of the ASP.NET 4.5 Web Forms site. Theres more code in the project than I have
discussed here, but its either standard ASP.NET code that falls outside the scope of this article, or it is code similar to
the code that I did present in this article.
Summary
In this article you saw how to implement a data-driven web site built with ASP.NET 4.5 Web Forms with model binding
(new to ASP.NET 4.5) and using the repository and model projects created in earlier articles in this series. As you saw,
its pretty straight forward to implement these pages using either the built-in data-bound controls, or using a more
custom code oriented approach where you have more control over the code as shown in the AddEditPerson.aspx
page.
Most of the code needed is standard ASP.NET code. In the Code Behind of the pages the various model binding
methods make use of the repository and unit of work classes. To avoid instantiating these classes over and over again
in all your ASPX pages, the RepositoryHelper class contains two factory methods that return an instance of the
requested type. Should you ever want to use another repository (with a NHibernate or other ORM implementation for
example), then all you need to update are these two helper methods.
Although MVC and Web Forms are probably the two most likely frontend implementations for an ASP.NET framework
like this, there are other options as well. In the next article, you see how to expose (some of) your repository methods
over a WCF service. In the article that follows you see how to build a command line tool to import existing data from
other sources, such as a CSV file.
Stuff I Like to Do
I only use the data-bound controls for simple data structures. E-mail addresses and phone numbers are good
candidates as they only have a few properties. And even then you saw how difficult it can be to do relatively
simple stuff as using an enum for one of the objects properties. I use the hand coded data access pages for
complex types such as Person. You recover the time spent on creating the initial UI controls by having to spend
less time on duplicating the code in the Item and EditItem templates and on handling the many events of the
data-bound and data source controls.
Although not shown in this project, its easy (and recommended) to use UI frameworks like jQuery UI or Kendo
UI. These frameworks make it easy to create good-looking UIs with little effort.
I like to group files in the project by their type. In the sample project, I stored the two helper classes in the
Helpers folder and all the Web Forms for managing contact people in the People folder. Although you could
theoretically store everything in the root or pretty much anywhere else, I find that a structure like this makes it
easier to find your files and maintain the application.
Links in this Document
(1) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part07/Figure7-1_WebForms_People_list.png
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part07/Figure7-2_WebForms_Edit_Person.png
(3) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part07/Figure7-3_WebForms_Edit_Address.png
(4) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part07/Figure7-4_WebForms_EmailAddresses.png
(5) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part07/Figure7-5_Model_Architecture.png
ASP.NET N-Layered Applications - Implementing a Web Forms 4.5 Frontend (Part 7)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 132 of 162
ASP.NET N-Layered Applications - Implementing a WCF 4.5
Frontend (Part 8)
This is Part 8 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a WCF service that makes use of the model and repository
projects I have shown in the first five articles in this series. The WCF service can be used by different types of
applications to access contact people and their related data.
Introduction
In this article, Ill show you how to build a WCF service that can expose contact data to calling applications over the
internet or local network. WCF is widely accessible from other application types so its a great platform to share data
with other applications, whether they are based on .NET or not.
In this article, Ill cover the following topics:
How to use StructureMap to inject repositories and units of work in your WCF service.
How to design your service API.
How to Unit Test your service methods.
How to return and access data.
This wont be a very long article as a lot of it has already been discussed, or is based on common WCF functionality.
However, I decided to include this part in the series to give you a complete picture of using the repositories and
models in a variety of applications.
Under the hood, this WCF service application uses the PeopleRepository, targeting the Entity Framework for all data
access. To see how it all fits together, heres the architecture diagram showing the WCF frontend application and how
its related to the other components in the system:
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 133 of 162
(1) See Links in this Document at the end for the full URL of this image.
Figure 8-1 The N-Layer Architecture Diagram
Youll see another view on the diagram a little later in this article when View Models are discussed.
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 134 of 162
Using StructureMap for Dependency Injection (DI)
Just like in an ASP.NET MVC application, it could be desirable to use Dependency Injection in your WCF services. The
biggest benefit is that it makes your services testable. Since a WCF Service is a normal class, you can instantiate it
and call its methods, just like any other class. For example, the following WCF Service (found in the
Spaanjaars.ContactManager.Web.Wcf project):
can be tested like this:
The first test ensures that the constructor of the service throws an exception if you dont supply a valid
IPeopleRepository. The sample project contains two more tests; one to test the IUnitOfWorkRepository, the other
to ensure the constructor does not throw an exception if both objects are supplied correctly. Although your code is
likely to crash elsewhere when you dont supply the correct objects in the constructor, I like these kinds of tests as
they clearly enforce code by contract and fail fast to be implemented in the service, which will avoid problems
further down the road.
Note: for more information on testing for exceptions using FluentAssertions, check out the documentation at:
http://fluentassertions.codeplex.com/documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ContactManagerService : IContactManagerService
{
private readonly IPeopleRepository _peopleRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;

public ContactManagerService(IPeopleRepository peopleRepository,
IUnitOfWorkFactory unitOfWorkFactory)
{
if (peopleRepository == null)
{
throw new ArgumentNullException("peopleRepository", "peopleRepository is null.");
}
if (unitOfWorkFactory == null)
{
throw new ArgumentNullException("unitOfWorkFactory", "unitOfWorkFactory is null.");
}
_peopleRepository = peopleRepository;
_unitOfWorkFactory = unitOfWorkFactory;
}

public PersonModel GetPerson(int id)
{
var person = _peopleRepository.FindById(id);
return new PersonModel {FirstName = person.FirstName, Id = person.Id};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[TestClass]
public class ContactManagerServiceTests : ServiceTestBase
{
[TestMethod]
public void ContactManagerServiceRequiresRepository()
{
Action act = () => new ContactManagerService(null, new FakeUnitOfWorkFactory());
act.ShouldThrow<ArgumentNullException>().WithMessage("peopleRepository is null",
ComparisonMode.Substring);
}

[TestMethod]
public void GetPersonByIdReturnsCorrectPerson()
{
var service = new ContactManagerService(new FakePeopleRepository(),
new FakeUnitOfWorkFactory());
var person = service.GetPerson(24);
person.LastName.Should().Be("Youngest Lastname");
person.Id.Should().Be(24);
}
}
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 135 of 162
The second test, GetPersonByIdReturnsCorrectPerson, checks whether the service method calls the FindById
method on the IPeopleRepository that is passed in and then constructs a correct PersonModel based on the return
value of FindById. For this to work, I implemented FindById in the fake repository and had it return one of the
available persons in the list. Youll see more of the GetPerson method after I have showed you how to set up
Dependency Injection in a WCF project.
To enable DI in a WCF project using StructureMap, follow these steps:
Install the package StructureMap into your WCF project.
Add a few code files to the project. Most of these are boiler plate files that you can add to any WCF project
without modification. You could even add them to the Infrastructure project or other shared class library if
youre willing to reference WCF related libraries such as System.ServiceModel.Activation.
Write a method that initializes StructureMap, similar to how I did it in the ASP.NET MVC project.
Modify the markup of your service method so it uses a custom ServiceHostFactory.
You see these steps in detail next.
Install StructureMap
This is easy. Just execute Install-Package StructureMap from the Package Manager Console window. Make sure
that the WCF project is selected in the Default project drop-down list.
Add Code Files to the Project to Define a Custom ServiceHostFactory and other Custom Types
In the root of the WCF project in the sample application you find a folder called StructureMap. It has five files, four of
which start with StructureMap:
Figure 8-2 Solution Explorer Showing StructureMap files for the WCF project
These classes are based on the work by Jimmy Bogard (who came up with the initial solution) and Scott Griffin (who
refined the code and fixed some issues.) You can find more background information here:
http://lostechies.com/jimmybogard/2008/07/30/integrating-structuremap-with-wcf
http://www.sgriffinusa.com/2011/02/setting-up-wcf-to-use-structuremap.html
You find the slightly modified classes in my sample project or you can refer to the online articles for the original
implementation.
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 136 of 162
Using Jimmys and Scotts work, all I needed to do was add the files to my project, and write a single class that sets up
StructureMap.
Write a method that Initializes StructureMap
The configuration code for StructureMap can be found in the Ioc.cs file. It looks like this:
This is almost identical to the code in the ASP.NET MVC project: it tells StructureMap to resolve types using the default
conventions (when requested to return an ISomething, StructureMap will try to use the Something type) and to scan
all assemblies in the Bin folder. In addition, it sets up EFUnitOfWorkFactory as the type to return when an
IUnitOfWorkFactory is requested.
Modify the Markup of the Service
To tell WCF to use another ServiceHostFactory that returns services whose constructors can receive injected types,
you need to modify the Markup of the service. You see how to do this in the next section when the actual service is
built, but if you want to see the code, heres how it looks:
The Factory attribute points to my custom StructureMapServiceHostFactory that in turn is able to return concrete
instances of my service(s) with the proper dependencies injected in the services constructor.
Adding the Service to the WCF Project
To add the service to your WCF project, right-click the project in the Solution Explorer, choose Add | New Item and
then choose WCF Service. In my project, I named the service ContactManagerService, giving me the following files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class Ioc
{
public static void Initialize()
{
ObjectFactory.Initialize(scanner =>
{
scanner.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.WithDefaultConventions();
});
scanner.For<IUnitOfWorkFactory>().Use<EFUnitOfWorkFactory>();
});
}
}
1
2
3
4
<%@ ServiceHost Language="C#" Debug="true"
Service="Spaanjaars.ContactManager45.Web.Wcf.ContactManagerService"
CodeBehind="ContactManagerService.svc.cs"
Factory="Spaanjaars.ContactManager45.Web.Wcf.StructureMap.StructureMapServiceHostFactory" %>
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 137 of 162
Figure 8-3 Solution Explorer Showing the Service Files
The .svc file is the actual service file that will be called by remote systems. Its code behind contains the actual
implementation, The IContactManagerService file contains an interface that your service must implement, and where
you define the methods you want to expose from your service.
With the service added, I then had to update the Factory attribute in the markup of the .svc file. To do that, I right-
clicked ContactManagerService.svc and chose View Markup. Double-clicking the svc file itself wont work as it will
open its code behind file instead. I then added the following Factory attribute to the code after the Code Behind
attribute that was already there:
Now that the service is added and configured for DI, the next logical step is defining its public API.
Designing your Service API
A WCF service is typically based on an interface that defines the members that you want to expose publicly. But which
members do you want to expose? That all depends on your business requirements. In the sample application I decided
to keep things relatively simple, so its easier to focus on the design principles rather than on the actual
implementation. My service will support the following features:
Name Description
GetPerson (int id) Returns a PersonModel based on the incoming ID.
Contains the two addresses, but no phone numbers or
e-mail addresses.
InsertPerson(PersonModel personModel) Enables you to insert a new person. Does not support
inserting phone numbers or e-mail addresses.
UpdatePerson(PersonModel personModel) Enables you to update an existing person. Does not
support inserting phone numbers or e-mail addresses.
DeletePerson(int id) Enables you to delete an existing person.
This leads to the following proposed interface:
1 Factory="Spaanjaars.ContactManager45.Web.Wcf.StructureMap.StructureMapServiceHostFactory"
1
2
public interface IContactManagerService
{
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 138 of 162
In WCF, its recommended to put attributes on types and members you want to expose through the service, resulting
in the following interface:
In the sample application the actual return type of InsertPerson and UpdatePerson is different. Youll see why this is
next.
Returning and Accepting Data
In order to build a flexible solution that remains easy to maintain in the future, its important that your WCF services
dont return types from your model directly. First of all, you may be exposing too much data, leaking more details than
you may want to. But another important reason for not returning model types directly is flexibility. A WCF service
serves as a contract between the service and any consuming client application, which means that as long as the
service is publicly available, you cant change the members of the service or the types they return. For example,
renaming a property of the Person class would result in a breaking change for all applications consuming your service.
If you put a layer of View Models on top of your model types, you can freely change the underlying implementation
without breaking the service contract. Figure 8-4 shows how View Models are flowing between the WCF service project
and external applications that use the service:
3
4
5
6
7
PersonModel GetPerson(int id);
int InsertPerson(PersonModel personModel);
void UpdatePerson(PersonModel personModel);
void DeletePerson(int id);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[ServiceContract]
public interface IContactManagerService
{
[OperationContract]
PersonModel GetPerson(int id);

[OperationContract]
int InsertPerson(PersonModel personModel);

[OperationContract]
int UpdatePerson(PersonModel personModel);

[OperationContract]
void DeletePerson(int id);
}
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 139 of 162
(2) See Links in this Document at the end for the full URL of this image.
Figure 8-4 View Models in the WCF Service Project
In the sample application I created two main View Model types that are returned by the service: PersonModel and
AddressModel that look as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[DataContract]
public class PersonModel
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public DateTime DateOfBirth { get; set; }
[DataMember]
public AddressModel HomeAddress { get; set; }
[DataMember]
public AddressModel WorkAddress { get; set; }
}

ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 140 of 162
For more information about the DataContract and DataMember attributes, check out the following links:
http://msdn.microsoft.com/en-us/library/ms733127.aspx
http://stackoverflow.com/questions/4836683/wcf-datacontract
Note that the PersonModel has two properties of type AddressModel. Furthermore, PersonModel does not have
properties for the e-mail address and phone number collections. PersonModel is used as the type returned for
GetPerson as well as an input parameter for InsertPerson and UpdatePerson. This doesnt have to be the case and
you could easily create different View Models for different methods.
I use AutoMapper to map between the Person and Address on one side and the PersonModel and AddressModel on
the other side, with this configuration code that should look very familiar by now:
When mapping to a Person, I am ignoring five properties. Just as an example, I am ignoring the Type property. Inside
the service, Ill set this type to a hardcoded value. Obviously, you can include the Type property as well so external
code could explicitly set it. I am ignoring the date properties as they are set by the Entity Framework automatically.
Finally, I am ignoring the contact data as I decided not to implement them in this service to keep things simple. Note
though that it is straight forward to add them; you could implement them as a List<EmailAddressModel> for example
and then provide AutoMapper configuration for it.
I am also using IsSourceValueNull to avoid overwriting an existing address with a null value if the calling code has
not submitted an address. You see how this is used later in the article.
You see what the mapper code for the ValidationResult is for in the next section that talks about error handling.
Returning Validation Errors
Imagine that the InsertPerson has been implemented, and that youre calling it from an external client application. If
all works out as expected, the calling code receives the ID of the newly created person. So far so good. But what if the
validation of the Person instance fails? For example, because the calling code didnt supply a first name? To handle
that situation, your code could throw an exception. However, depending on how you configured your WCF services,
those exceptions may never end up at the client, leaving them guessing as to why the insert failed. As an alternative,
18
19
20
21
22
23
24
25
26
27
28
29
[DataContract]
public class AddressModel
{
[DataMember]
public string Street { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public string ZipCode { get; set; }
[DataMember]
public string Country { get; set; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static class AutoMapperConfig
{
public static void Start()
{
Mapper.CreateMap<PersonModel, Person>()
.ForMember(x => x.Type, x => x.Ignore())
.ForMember(x => x.DateCreated, x => x.Ignore())
.ForMember(x => x.DateModified, x => x.Ignore())
.ForMember(x => x.EmailAddresses, x => x.Ignore())
.ForMember(x => x.PhoneNumbers, x => x.Ignore())
.ForMember(x => x.HomeAddress, y => y.Condition(src => !src.IsSourceValueNull))
.ForMember(x => x.WorkAddress, y => y.Condition(src => !src.IsSourceValueNull));
Mapper.CreateMap<Person, PersonModel>();

Mapper.CreateMap<AddressModel, Address>()
.ForMember(x => x.ContactType, x => x.Ignore());
Mapper.CreateMap<Address, AddressModel>();

Mapper.CreateMap<ValidationResult, ValidationResultModel>();
Mapper.AssertConfigurationIsValid();
}
}
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 141 of 162
your method could return a collection of ValidationResult instances. However, you cant have a method that returns
either an int or a collection of errors, unless you change the return type to an object which isnt really helpful.
The solution to this problem I typically use is to use a generic class that has two properties: the actual data you want
to return (as a generic T) and a collection of validation errors. Heres how the class could look:
The type of T is defined when instantiating the class as youll see in a moment. The Errors collection is of type
IEnumerable<ValidationResultModel>. I had to create the ValidationResultModel class because the
ValidationResult class from the DataAnnotations namespace is not marked as serializable and as such cannot be
sent back as a result from a WCF service. I am using AutoMapper once again to go from a ValidationResult to a
ValidationResultModel.
To return a valid int from a service method using this class, you can use code like this:
In this case, the Errors property is null. If you need to return errors instead, you can use code like this:
Here, the Data property is null, but now the Errors collection is filled. The code uses AutoMapper to convert the
collection of errors in the errors variable to a new List of ValidationResultModel.
For this code to work, the methods signature must be changed to this:
And the calling code can then use the return value as follows:
Implementing the Service
With all the hard work of creating interfaces, models, return types and mapping code done, implementing the service
is now pretty easy. For example, all you need for GetPerson is this:
1
2
3
4
5
6
7
8
9
[DataContract]
public class ServiceResult<T>
{
[DataMember]
public T Data { get; internal set; }

[DataMember]
public IEnumerable<ValidationResultModel> Errors { get; internal set; }
}
1 return new ServiceResult<int?> { Data = person.Id };
1 return new ServiceResult<int?> { Errors = Mapper.Map(errors, new List<ValidationResultModel>()) };
1
2
3
4
public ServiceResult<int?> InsertPerson(PersonModel personModel)
{
...
}
1
2
3
4
5
6
7
8
9
10
11
var personModel = new PersonModel { ... };
var result = wcfClient.InsertPerson(personModel);
if (result.Errors.Any())
{
// Deal with errors
}
else
{
int newId = result.Data.Value;
// Use the new ID of the person somehow
}
1
2
public PersonModel GetPerson(int id)
{
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 142 of 162
And InsertPerson can be implemented like this:
I configured AutoMapper to ignore the two address properties on PersonModel when they are null using
IsSourceValueNull. That means that existing addresses wont be overwritten by a null value.
Note that this WCF service will currently only save colleagues as that type is hardcoded in InsertPerson. Obviously,
you can change this behavior by making Type a member of PersonModel as well.
UpdatePerson is similar although it calls Undo on the Unit of work to undo any changes when any one of the objects is
in an invalid state. Finally, DeletePerson simply forwards the ID of the person to the Remove method on the repository
and then exits.
The WCF service now supports all CRUD operations on a contact person: Create, Read, Update, and Delete. Obviously,
you can expand this example any way you see fit. You could add support for e-mail addresses and phone numbers,
check whether the current user has access to view or modify a contact person (using WCF security or a custom
solution) and more, all using the same principles.
Stuff I Like to Do
I usually write unit tests for my AutoMapper code. Not for all of it but mostly for the exceptions. A test like
NullValueInSourceDoesNotOverwriteTarget that youll find in the code helps to ensure youre not
accidentally overwriting existing values with null values. This can prevent awkward bugs or data corruption
from happening.
I also write tests for my WCF services. By abstracting external dependencies as youve seen in this article, the
service methods become very easy to test. Since service methods are often used in machine-to-machine
scenarios its even more important they behave correctly as its less likely your end users will run into them and
report them to you.
Summary
In this article you saw how to use the contact manager applications repository and unit of work to expose application
data to the internet, and to accept requests to insert, edit and delete contact people. The article started with an
explanation of enabling Dependency Injection in a WCF. Although the code to implement this isnt very straightforward,
its pretty much the same code over and over again so it mostly comes down to copying a few existing files into your
project and then writing a bit of code to configure StructureMap.
You then saw how to design the API of the service, starting with the design of the interface. Heres where you define
the members of the service such as GetPerson, InsertPerson and so on. To decouple your service layer from your
3
4
5
var person = _peopleRepository.FindById(id);
return Mapper.Map(person, new PersonModel());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public ServiceResult<int?> InsertPerson(PersonModel personModel)
{
var person = new Person();
Mapper.Map(personModel, person);

// For demo purposes, let's assume we only accept colleagues.
// You could easily add Type to the PersonModel and let external code set it
person.Type = PersonType.Colleague;

List<ValidationResult> errors = person.Validate().ToList();

if (errors.Any())
{
var result = new ServiceResult<int?>
{ Errors = Mapper.Map(errors, new List<ValidationResultModel>()) };
return result;
}
using (_unitOfWorkFactory.Create())
{
_peopleRepository.Add(person);
}
return new ServiceResult<int?> { Data = person.Id };
}
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 143 of 162
applications model, the service doesnt expose your model types directly, but uses View Models instead. Once again,
AutoMapper is very helpful to minimize the code you need to write to map from one type to another.
At the end you saw the actual implementation of the service. As an example, I hard coded some of the incoming data
in the service; for example, I set the Type of a Person explicitly and fixed the addresses. If you want, you can also fix
issues like this in your model, or force calling code to only supply valid data.
Besides a WCF service theres another common way to get data into an application like the contact manager in an
automated way: using a command line tool to import data from an external resource. You see how to do this in the
next part in this article series.
Links in this Document
(1) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part08/Figure8-1_Model_Architecture.png
(2) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part08/Figure8-4_Architecture_Diagram.png
ASP.NET N-Layered Applications - Implementing a WCF 4.5 Frontend (Part 8)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 144 of 162
ASP.NET N-Layered Applications - Importing Data Using the
API (Part 9)
This is Part 9 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part youll see how to build a command line application to import data from an
external source (a CSV file in this case), using the applications repository and model classes. Although this article is
not related to ASP.NET directly, many ASP.NET developers may still benefit from it as importing data from an external
resource is a common activity for ASP.NET developers.
Introduction
Quite often when you build data-driven applications like the Spaanjaars ContactManager, you dont always start with a
green field project. Its quite likely you already have an existing system with its own database that contains data you
have to use in the new application. To get that data into your new application, you could import directly into SQL
Server, or you could use the applications API. The advantage of using the API is that you get all the type checking and
validation that has been built into the model classes. Using the by now familiar repositories and model classes, you can
quickly import data from any data source that .NET can communicate with and ensure only data that matches your
applications rules makes it into the system.
In this article, Ill show you how to import data from a CSV file using a third-party library called FileHelpers. You can
use the exact same techniques for other data sources such as databases (SQL Server, Oracle, Access, other OLEDB
and ODBC databases and so on), XML files, web services and more.
In this article, Ill cover the following topics:
How to read a CSV file line by line using the FileHelpers library.
How to deal with invalid or incomplete data in an import application.
How to ensure a great performance of the application.
Importing from a CSV File
In the sample application that comes with this article, you find a project called Spaanjaars.ContactManager.Import
in the Frontend folder. Its a C# Console Application designed to read a CSV file from disk, extract data from that file,
transfer that data into contact people and contact details and insert them in the database using the repository and
model classes youve seen in the first five articles in this series. Heres how the application looks in the Solution
Explorer:
Figure 9-1 Solution Explorer for the Spaanjaars.ContactManager.Import application
Ill discuss the three code files later in this article, and the CSV file called People.csv in the next section.
Introducing the CSV File
To make things as realistic as possible, I created a CSV file that is not error-free or optimal and contains a number of
issues that need to be resolved during the import. The following table lists the available columns in the file and the
possible problems the data in those columns can have.
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 145 of 162
Name Type Description
First name string The persons first name. Always present.
Last name string The persons first name. Always present.
Date of birth DateTime The persons date of birth in the format M/d/yyyy. The date is always present.
Type int The type of the person; matches the values in the PersonType enum.
Address 1 string These four columns contain the home address of the person. Not every field is
always filled. Some fields contain the text NULL to indicate a null value.
Zip 1 string
City 1 string
Country 1 string
Address 2 string These four columns contain the work address of the person. Not every field is
always filled. Some fields contain the text NULL to indicate a null value.
Zip 2 string
City 2 string
Country 2 string
Email string The persons e-mail address. Some e-mail addresses are in an invalid format.
This field can be null in which case it contains the text NULL.
Email type string The type of e-mail address. Can be PRIVATE or COMPANY or can be NULL when
the e-mail address is null. Note that these dont match the enum values directly
and thus need to be converted into the proper enum type.
Phone number string The persons phone number. Since no type is present in the file, the application
imports these as ContactType.Business.
Heres an example row:
The CSV file is copied to the applications Bin folder whenever it changes, and the application will use that file if youre
not explicitly specifying a full path to a file as an argument at the command line.
When the application is running, it will report the number of rows that have been imported successfully and the
number of rows that failed. It also reports the number of rows that are processed per second. Figure 9-2 shows the
application while running:
(1) See Links in this Document at the end for the full URL of this image.
Figure 9-2 The Command Line Application Importing Contact Data
If you wonder if I know that many people, the answer is no. I generated a huge amount of sample data in the SQL
Server database using Red Gates Data Generator
(2)
and then exported that to a CSV file. Part 10 has more details on
this tool.
1
2
Crystal,Palmer,7/6/1968,2,113 East Old Road,63867,30 New St.,Togo,55 Milton Road,
28027,93 West White Hague Road,Macao,[email protected],COMPANY,(845) 121-3652
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 146 of 162
Introducing the FileHelpers
You have a couple of different options when it comes to parsing a CSV file. You could write your own custom code to
do it, you can use the TextFieldParser that is part of the Microsoft.VisualBasic assembly, or you can use one of
the existing third party libraries such as CsvHelper (https://github.com/JoshClose/CsvHelper), CsvReader
(http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader) or FileHelpers (http://filehelpers.sourceforge.net/). I
have used FileHelpers a number of times in real-world projects in the past and it has served me well, so Ill use it in
this article again.
Importing a CSV file with FileHelpers is really easy and is typically a three-step process:
Install the FileHelpers library using NuGet.
Define a custom class that can hold the data for an individual row. Each field in the class maps to a column in
the source file. You must define the fields in the order they appear in the source file. You can use .NET types
like string, int and DateTime and the FileHelpersEngine will correctly populate them. You can use various
attributes to define the conversion from the source to the target to handle special cases.
Finally, you can loop over the individual rows in the source file using the FileHelperEngine. In my example, I
am using the FileHelperAsyncEngine class which lets you process rows as they are being read by the engine.
The alternative is the FileHelperEngine class which loads all rows at once which may consume more memory
when reading large files.
Ill show you each step in detail in the next sections.
Installing FileHelpers using NuGet
Once again, this is easy. Just execute Install-Package FileHelpers from the Package Manager Console window.
Make sure your import application is selected in the Default project drop-down list.
Define a Custom Class to Hold the Imported Data
My custom data class looks more or less like the CSV file I described earlier. For each column in the source file I create
a field. I also used .NET types for columns such as the DateOfBirth (a DateTime) and the Type (an int in this
example). Heres the full class (found in ImportPerson.cs):
As you can see, all you need to do is define a class, add a few fields, and then apply some attributes. The
DelimitedRecord attribute tells the engine that each column value is separated by a comma. The FieldConverter
attribute helps to convert source data to the target. In this example, I am also specifying the date format as it appears
in the source file. For more information on the attributes, take a look at the FileHelpers web site at:
http://filehelpers.sourceforge.net/.
Processing Contact Rows
Once the data class is setup, reading a CSV file and getting instances of ImportPerson back is really simple. Heres the
minimum amount of code you need to write:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[DelimitedRecord(",")]
public class ImportPerson
{
public string FirstName;
public string LastName;
[FieldConverter(ConverterKind.Date, "M/d/yyyy")]
public DateTime DateOfBirth;
public int Type;
public string Address;
public string Zip;
public string City;
public string Country;
public string Address2;
public string Zip2;
public string City2;
public string Country2;
public string Email;
public string EmailType;
public string PhoneNumber;
}
1
2
3
using (var importEngine = new FileHelperAsyncEngine<ImportPerson>())
{
importEngine.BeginReadFile(_fileName);
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 147 of 162
For the sample application, the foreach loop contains code like this (theres more, but most of it has to do with error
handling and writing the progress to the screen). You find this code in Program.cs inside the Main method.
This code creates a Person instance that is eventually added to the repository if its completely valid. I am using
AutoMapper again to go from an ImportPerson to a Person. Since the four properties of each address come from
separate columns in the source file, I needed some trickery to tell AutoMapper how to take those fields and turn them
into an Address. Heres the code for the AutoMapper configuration (inside AutoMapperConfig.cs):
ResolveUsing uses a lambda expression that receives an instance of the ImportPerson and returns an instance of
Address. Within the function body I can access the relevant fields to construct a new Address. I really like this as it
enables me to define all mapping in a central location so my core application is free from stuff like this.
I am taking a slightly different approach with the TryAddEmailAddress and TryAddPhoneNumber methods. Heres the
code for the first of these two methods:
When the column for the phone number does not contain an empty string or the word NULL, I add a phone number to
the Persons PhoneNumbers collection. As a contact type I am hardcoding ContactType.Business as the source file
contains no relevant information to determine the real type. This is just an implementation choice. How you handle
exceptions like these depends entirely on the source file and the business requirements of your application.
Note that earlier I said that the source file contains invalid data for the addresses and e-mail addresses. For example,
an address may not be complete and one or more columns may contain the value NULL. Once again, how you handle
that depends on your requirements. As an example, I wrote two methods that can set the address properties to null
4
5
6
7
8
9
foreach (ImportPerson importPerson in importEngine)
{
// Work with importPerson here.
}
importEngine.Close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var person = new Person();
Mapper.Map(importPerson, person); // Maps the ImportPerson to a person using AutoMapper.

TryAddEmailAddress(importPerson, person);
TryAddPhoneNumber(importPerson, person);

FixAddress(person.HomeAddress, changeMissingDataToNull: false);
FixAddress(person.WorkAddress, changeMissingDataToNull: false);

if (!person.Validate().Any())
{
PeopleRepository.Add(person);
// Todo: Commit changes
}
1
2
3
4
5
6
7
8
9
10
11
Mapper.CreateMap<ImportPerson, Person>()
.ForMember(x => x.Id, x => x.Ignore())
.ForMember(x => x.DateCreated, x => x.Ignore())
.ForMember(x => x.DateModified, x => x.Ignore())
.ForMember(x => x.EmailAddresses, x => x.Ignore())
.ForMember(x => x.PhoneNumbers, x => x.Ignore())
.ForMember(x => x.HomeAddress, x => x.ResolveUsing(ip => new Address(ip.Address,
ip.City, ip.Zip, ip.Country, ContactType.Personal)))
.ForMember(x => x.WorkAddress, x => x.ResolveUsing(ip => new Address(ip.Address2,
ip.City2, ip.Zip2, ip.Country2, ContactType.Business)));
Mapper.AssertConfigurationIsValid();
1
2
3
4
5
6
7
private static void TryAddPhoneNumber(ImportPerson importPerson, Person person)
{
if (!string.IsNullOrEmpty(importPerson.PhoneNumber) && importPerson.PhoneNumber != "NULL")
{
person.PhoneNumbers.Add(importPerson.PhoneNumber, ContactType.Business);
}
}
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 148 of 162
or to <Unknown> when they contain invalid data:
The value <Unknown> will eventually make it to the database, but null may be rejected if at least one of the other
three properties of Address does have a value (remember: its all or nothing. No value for all properties is considered
null, but at least one value means the Validate method of Address requires all values to be set).
Right before the code tries to add the Person instance to the repository, it calls Validate. When the Person, or any of
its properties contain invalid data, the person is not added to the repository. What you do in this case depends on your
business requirements. You can log the error and write the line number to a file for later processing or you could try to
automatically fix problems as I did with the Addresses.
Once the person is added to the repository, the final thing to do is save the changes to the database. For the import
application that deals with many entities at the same time, this works a bit differently as youll see in the next section.
Ensuring Great Performance
When saving the changes in the repository to the database, you have a couple of options. For example you could try to
save all changes at once, with code like this:
For every valid row in the CSV file, a new Person is added to the repository. As youve seen in Part 5 of this series, at
the end of the using block the UnitOfWork automatically calls SaveChanges which submits the changes to the
database. In testing I found this to be quite a slow method when dealing with many entities. The reason for this is that
inserts in an EF DbContext become slower when the context already contains other entities. You wont notice this with
a few rows, but it becomes quite obvious with hundreds or thousands of rows in the source file.
An alternative to solution to this problem looks like this:
In this example a new UnitOfWork is created for each individual person (inside the foreach loop) which is then saved
to the database. This also doesnt perform well, because of all the overhead of instantiating data contexts and SQL
Server connections. I found that saving the people entities every 30 rows or so gave me the best performance. For
that to work, I had to make two changes. First, I needed to keep track of the number of new people being added using
the success variable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static Address FixAddress(Address address, bool changeMissingDataToNull)
{
string street = SetValueToNullOrUnknown(address.Street, changeMissingDataToNull);
string zipCode = SetValueToNullOrUnknown(address.ZipCode, changeMissingDataToNull);
string city = SetValueToNullOrUnknown(address.City, changeMissingDataToNull);
string country = SetValueToNullOrUnknown(address.Country, changeMissingDataToNull);
return new Address(street, city, zipCode, country, address.ContactType);
}

private static string SetValueToNullOrUnknown(string value, bool changeMissingDataToNull)
{
string temp = changeMissingDataToNull ? null : "<Unknown>";
return string.IsNullOrEmpty(value) || value == "NULL" ? temp : value;
}
1
2
3
4
5
6
7
8
using (var uow = new EFUnitOfWorkFactory().Create())
{
foreach (ImportPerson importPerson in engine)
{
...
PeopleRepository.Add(person);
}
}
1
2
3
4
5
6
7
8
foreach (ImportPerson importPerson in engine)
{
using (var uow = new EFUnitOfWorkFactory().Create())
{
...
PeopleRepository.Add(person);
}
}
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 149 of 162
Secondly, I had to call Commit on the IUnitOfWork on every 30 rows and pass true to have it clear out the existing
data context. The final solution looks like this:
The Commit method saves the changes in the DbContext by calling SaveChanges:
The resetAfterCommit parameter clears the existing data context which gets rid of the previously saved Person
entities. On the next call to GetDataContext, a new instance is created and returned.
The remaining records that are not saved by calling Commit are saved automatically at the end of the using block.
This import implementation actually drove part of the design of the IUnitOfWork interface and concrete
implementations. Initially, I did not design a Commit method as committing would happen automatically. For most web
applications where you only have a few entities that need to be saved at the same time, that works really well.
However, for bulk inserts like this one, I really needed a better solution, and a Commit method to send the changes to
the database explicitly as well as a means to clear out the existing data context turned out to be the best solution.
I tested the performance of the various alternatives by inserting 30,000 rows from a CSV file for each option. The
table below shows the performance numbers for each alternative:
Strategy Number of items per second Time
1 Unit of work for the entire CSV file 10 ~ 40 minutes
1 Unit of work per line in the CSV file A few A few hours
Save every 10 rows 546 54 seconds
Save every 30 rows 671 44 seconds
Save every 100 rows 551 54 seconds
When using one unit of work per line in the CSV file, performance degraded up to a point where less than a row per
second was processed. I canceled the import after almost an hour at which time it had processed around 20 percent of
the rows.
Saving every 30 rows seemed to give the best performance on my machine and for my application. Its important to
test out settings like this yourself, as a lot of it depends on the specifics of your application. If raw speed is very
important you could also consider alternative solutions such as bulk copy, or disabling features like validation and
change tracking on the DbContext. More details can be found here:
http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/
http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework/5942176#5942176
http://stackoverflow.com/questions/6107206/improving-bulk-insert-performance-in-entity-framework
When I disabled validation and change tracking I was able to insert around 960 items a second; a performance
improvement of over 40 percent compared to the best performing solution. If you decide to use this feature, be sure
to make it configurable so only tools like the Importer use it and other code still uses the default validation and
change tracking mechanisms. I havent implemented this in the sample application as I feel it may not be necessary in
the majority of the cases and should be treated as a one-off implementation.
1
2
3
4
5
PeopleRepository.Add(person);
if (success % 30 == 0)
{
uow.Commit(true);
}
1
2
3
4
5
6
7
8
public void Commit(bool resetAfterCommit)
{
DataContextFactory.GetDataContext().SaveChanges();
if (resetAfterCommit)
{
DataContextFactory.Clear();
}
}
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 150 of 162
Stuff I Like to Do
With an import tool like this one, I am not overly concerned with testing or dependency injection. Most of the
testing comes down to integration testing anyway (where you import real source files and validate them
directly in a real database) since the import code is pretty straightforward (and thus testing mainly comes
down to making sure the data lands where it should). This means I dont mind instantiating classes like
PeopleRepository directly in the Main method.
I do use AutoMapper for applications like this, as it makes it really easy to convert from one type to another. In
this example, I could have used methods like ResolveUsing to fix the problem with the non-matching contact
type column. I chose not to do this to show you another alternative. However, using AutoMapper for the
conversion would be similar to how the Address objects were filled with data from the ImportPerson class.
I do like to keep an eye on performance. Often these applications are used only once to do the final import and
then it doesnt really matter if it takes 20, 30 or 120 minutes to complete. However, by analyzing the
performance of the application you may find areas that can be improved for other scenarios as well, leading to
a better overall performance.
Summary
In this article you saw how to import contact data from a CSV file using the repository and model classes introduced in
earlier parts of this article series as well as an external library called FileHelpers. With FileHelpers, importing a CSV file
is really straightforward. All you need to do is define a data class that will hold the data coming from each row, and
then write some code to loop over all the rows in the source file using the FileHelperEngine and
FileHelperAsyncEngine classes. I use AutoMapper to convert the imported type into a Person model instance which I
can then feed into my repository.
At the end I discussed a few performance implications that come to light with an import application like this one.
Performance issues may go unnoticed when dealing with only a few entities, but they become more apparent when
dealing with thousands of them.
Links in this Document
(1) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part09/Figure9-2_CommandlineTool_Output.png
(2) http://www.red-gate.com/products/sql-development/sql-data-generator/
ASP.NET N-Layered Applications - Importing Data Using the API (Part 9)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 151 of 162
ASP.NET N-Layered Applications - Extensions, Tools and
Wrapping Up (Part 10)
This is Part 10 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity
Framework 5 Code First. In this part Ill discuss a few miscellaneous topics that I havent touched in previous articles
in the series.
Possible Extensions
In this section Ill discuss a few possible extensions to the sample application. I may update this section in the future if
I get questions from readers asking how to implement specific functionality.
Implementing Security
In my previous article series on building N-Layered applications with ASP.NET I spent an entire article on the topic of
security
(1)
. In the new series I havent touched on this subject at all. The reason for this is that not much has
changed and most of the concepts discussed in that article still apply.
Note that when youre using MVC as your frontend, you can also make use of the authorization attributes such as
Authorize and AllowAnonymous, to control access to the action methods in your controllers.
For more details, check out the following links:
http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-
new-allowanonymous-attribute.aspx
http://www.davidhayden.me/blog/asp.net-mvc-4-allowanonymous-attribute-and-authorize-attribute
Implementing Concurrency
Although not implemented in the sample code, implementing concurrency handling is relatively straightforward. Heres
a high-level description of the steps involved to implement concurrency handling in the MVC frontend:
Add a Version property to your entity of type byte[].
Configure EF to treat that property as the row version of your entity.
Modify the View Models and views to support the Version property. When youre editing an entity, you need to
store the row version in a hidden field. Then when the page is posted back, you get the version number from
the hidden field and assign it to the entity that is being edited. Then when the changes are saved, EF will use
that number and compare it against the version in the database and throw a concurrency exception when the
two values dont match. Theres a caveat you need to be aware of when assigning the row version as youll see
in the description of step 5.
When saving changes to an existing entity, make sure it uses the correct version number.
Handle the error in the UI.
Ill describe each of these steps in more detail next.
Add a Version Property to Your Entity
You can add the property to each individual entity, or to the base class DomainEntity. I usually add it to individual
entities as not all my entities need concurrency handling. I also create an IHandlesConcurrency interface so I can tell
whether an entity handles concurrency or not. This is useful in step 3 as youll see soon. For the Person entity, I could
end up with something like this:
1
2
3
4
5
6
7
8
9
10
11
12
public interface IHandlesConcurrency
{
byte[] Version { get; set; }
}

...

public class Person : DomainEntity<int>, IDateTracking, IHandlesConcurrency
{
// Other members go here
public byte[] Version { get; set; }
}
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 152 of 162
Configure EF to Treat that Property as the Row Version of Your Entity
Again, this is simple to do as the Fluent API has a handy IsRowVersion method. Inside my PersonConfiguration
class I can add the following code:
Modify the View Models and Views to Support the Version Property
First, you need to add a Version property to the CreateAndEditPerson class.
You then need to store the value of the Version property in the view. Heres an example from the Edit view:
When Saving Changes to an Existing Entity, Make Sure it Uses the Correct Version Number
This is a bit of a weird step. When you configure the Version property as the RowVersion, EF treats this field as store
generated. That means that when it needs to send its value to the database, it will use the original value, not the
value that has been retrieved from the hidden form field (even though that has been assigned as the new value for the
Version property when mapping from a CreateAndEditPerson to a Person instance in the Edit action method). To
work around this, you can tell EF to use the current value rather than the original value. Heres where the
IHandlesConcurrency interface comes in handy. In SaveChanges you can find all entities that implement this interface
and then reassign the Version number:
This way, the version retrieved from the form is used in the concurrency check.
Handle the Error in the UI
Finally, you need to handle the error in the UI. How you do this is up to you; you can intercept the problem by using a
catch block for a DbUpdateConcurrencyException. Then inside that block you can tell the user what went wrong and
offer them a chance to reload the changes from the database or force their new values to be submitted to the
database.
Using Red Gates SQL Data Generator to Generate Relevant
Sample Data and Find Performance Issues
When building an application like this, its useful to have good sample data. While you certainly can (and should) insert
data using unit tests, there are times where you need more data. For example, when doing performance testing or
profiling, it really helps to stuff your tables with tens of thousands of rows to reveal any issues with indexes etc. One
solution is to use the Seed method of your database initialization class. Writing a quick loop that adds a lot of entities
is easily done.
Another alternative that I often use is Red Gates SQL Data Generator
(2)
. Using this tool you can generate sample
data for your database. The price for the tool as a stand-alone version is 220 but it also comes bundled in the SQL
1
2
3
4
5
6
7
8
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
Property(x => x.Version).IsRowVersion();
// Other code here
}
}
1
2
3
4
5
6
@using (Html.BeginForm())
{
... Other code here
@Html.HiddenFor(model => model.Version)
... Other code here
}
1
2
3
4
5
6
7
8
if (item.State == EntityState.Modified)
{
var supportsConcurrency = item.Entity as IHandlesConcurrency;
if (supportsConcurrency != null)
{
item.Property("Version").OriginalValue = item.Property("Version").CurrentValue;
}
}
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 153 of 162
Developer Bundle and the SQL Toolbelt packages. What I like about this tool is that it can generate data that looks as
real as possible. The tool has smarts built-in to recognize columns by their name and type and then recommends the
appropriate sample data. For example, when using the tool to generate data for the People table, it recognizes the
FirstName and LastName column (and many others as well) and suggests to fill them with sample data contain names.
Figure 10-1 shows an example:
(3) See Links in this Document at the end for the full URL of this image.
Figure 10-1 Red Gates SQL Data Generator
Using this tool, inserting a million rows in the People table takes less than a minute. With this large amount of sample
data, I was able to find a few areas where I could improve performance. For example, if you sort the grid with all the
people based on their ID, youll notice this is really fast as the ID has been set up as a (clustered) index as its also the
primary key. However, when you try to sort on the full name of date of birth columns youll notice performance is not
great. In this example it was easy to guess what the solution is - (add indexes for the first name, last name and date
of birth columns to the database) but for more advanced scenarios having a good and large data set will help you find
issues in your code and database. To make sure these indexes get added to the database even when it is regenerated
after the model changes, you can execute the following code from a custom database initializers Seed method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyInitializer : DropCreateDatabaseIfModelChanges<ContactManagerContext>
{
protected override void Seed(ContactManagerContext context)
{
context.Database.ExecuteSqlCommand(@"
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20130505-160821] ON [dbo].[People]
(
[DateOfBirth] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)");

context.Database.ExecuteSqlCommand(@"
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20130505-160727] ON [dbo].[People]
(
[FirstName] ASC,
[LastName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)");
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 154 of 162
Now whenever the database is recreated two indexes for the first name, last name and date of birth columns are
created automatically.
For more advanced scenarios you can also use SQL Servers query plan analyzer to figure out how to best optimize
your database.
For more information about setting up Red Gates Data Generator, check out these resources:
http://imar.spaanjaars.com/523/avoiding-the-works-on-my-machine-syndrome
http://documentation.red-gate.com/display/SDG20/SQL+Data+Generator+2.0+documentation
Using Entity Framework Profiler from Hibernating Rhinos
Another great tool to help you with performance problems is the Entity Framework Profiler from Hibernating
Rhinos
(4)
. This tool gives you valuable insight and perspective into [the] usage of Entity Framework by analyzing
your queries during run-time. It can help you find common problems like Select N+1
(5)
and it provides tips to help
you solve them. The tool costs $287.00 for a yearly subscription or $389.00 for a standard license. Entity Framework
Profiler is also available in the Uber Profiler
(6)
that contains profilers for other ORMs as well.
Using Entity Framework Profiler is straightforward and involves a few simple steps:
Download the Entity Framework Profiler.
Add a reference to one of the applications assemblies.
Write some startup code in your applications Gobal.asax file (or other startup file for non-web projects).
Start the profiler.
Analyze the results.
Ill describe each of these steps in the following sections.
Download the Entity Framework Profiler
You can download the Entity Framework Profiler from its products page at http://www.hibernatingrhinos.com/products
/EFProf. Once youve downloaded the application you can request a trial key from this page:
http://www.hibernatingrhinos.com/products/efprof/trial which will be sent to you by e-mail. You dont need to install
anything, all you need to do is extract the ZIP file to a convenient location such as C:\Tools\EFProf.
Add a Reference to one of the Applications Assemblies
In order to see profiling data in the tool, you need to add a reference to the
HibernatingRhinos.Profiler.Appender.dll assembly (from the EF Profiler directory) to the application youre
profiling. This can for example be your MVC or Web Forms project or your Integration tests project. See the file How to
use.txt in the applications main folder for more details about using the profiler in a production environment.
Write Code in your Applications Startup File
Next, you need a single line of code to start the profiling. For a web project you need to add the following line of code
to the Application_Start handler in Global.asax:
If youre profiling your integration tests, you could add this code to the constructor of the IntegrationTestBase class.
Start the Profiler and Your Application
Next, from the EF Profiler folder, startup EFProf.exe. Then start up your application (browse to a web project or run
the unit tests) to see the results in the profiler as shown in Figure 10-2:
1 HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 155 of 162
(7) See Links in this Document at the end for the full URL of this image.
Figure 10-2 Entity Framework Profiler
Analyze the results
In Figure 10-2 you can see the results from browsing to the main list of people. The Alerts column on the right is
empty which means that the EF Profiler hasnt found any problematic queries. However, to show you how this works,
lets introduce an issue in the FindById method in the base Repository<T> class. It currently looks like this:
In order to introduce a (major) issue, I changed the code to this:
Notice the inclusion of ToList, a common mistake made by developers. ToList causes an immediate execution of the
query which means that all rows are retrieved from the database into EF. The SingleOrDefault method is then
executed against the in-memory collection of objects, not on the database. You wont notice this with a few rows in the
database, but this surely breaks or causes bad performance with thousands or more rows. EF Profiler flags this issue
as follows:
1
2
3
4
public virtual T FindById(int id, params Expression<Func<T, object>>[] includeProperties)
{
return FindAll(includeProperties).SingleOrDefault(x => x.Id == id);
}
1
2
3
4
public virtual T FindById(int id, params Expression<Func<T, object>>[] includeProperties)
{
return FindAll(includeProperties).ToList().SingleOrDefault(x => x.Id == id);
}
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 156 of 162
(8) See Links in this Document at the end for the full URL of this image.
Figure 10-3 Entity Framework Profiler Highlighting Issues
The profiler is flagging two issues. It has noticed that your query uses an unbounded result set and that a large
number of rows are returned. The first issue is caused by the ToList method. This executes a query against the
database without a WHERE clause, which means all rows are returned from the database. In this case, the second issue
is a directly related to the first: since the table contains many rows and there is no restrictive WHERE clause, a large
number of rows are returned to the calling application. You may also see these alerts independent of each other: if you
query a large table with a WHERE clause thats not very restrictive (for example Id > 1) you would still see the first
alert. A small table that is being queried without a WHERE clause would cause the second alert to appear in the tools
Alerts column.
While these tools are great to help figure out problems in the code and setup of your application, you may also have
the need to find out issues in your application while its running in production. To gain more information about what
your site does at run-time you can implement a logging strategy, discussed next.
Using NLog for Extensive Logging
Its not uncommon that one of your applications in production suddenly doesnt behave as expected. With the many
layers in a layered application it may not always be easy to figure out whats going. Imagine you have an external
application that accesses your WCF service but receives null when asking for a specific contact person. On a
production server, it may be difficult to track down whats going on. Is the calling application making a mistake by
passing in an ID that doesnt represent an existing person? Or maybe the person is deleted from the database while it
shouldnt have been? Or maybe someone accidentally deployed a web.config file that targets the staging server
instead of the production server. Investigating an issue like this can be quite time consuming.
You can take out a lot of the guesswork if your application logs its activities into a log file. Then whenever something
unexpected occurs, you can check the log file to see whats going on. Logging is really easy to do using an existing
logging framework such Log4Net
(9)
, the logging framework thats part of the Microsoft Enterprise Library
(10)
,
NLog
(11)
or others. For a feature by feature comparison of some these frameworks, check out
http://www.dotnetlogging.com/comparison/. Note: the information you find here is biased a bit, as this site is owned
by Gurock Software, the company that makes the commercial SmartInspect logging framework. Take it with a grain of
salt.
The option I usually choose is NLog. Its free to use (its licensed under a BSD license), its easy to configure and yet
its powerful enough to fulfil all of your logging needs. I usually reference the NLog library directly in my application (I
set it up using NuGet) and write code directly against the Logger classes in the NLog namespace. Although this creates
a dependency between my application and NLog, I am usually OK with that. It doesnt interfere with Unit Testing (as
youll see soon) and I usually dont have the need to swap out NLog for another framework. If you do have that need,
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 157 of 162
you could create (or use an existing) interface for your logging methods and then inject a concrete log implementation
at runtime using your DI tool of choice. More information can be found here:
http://netcommon.sourceforge.net/
http://stackoverflow.com/questions/5646820/logger-wrapper-best-practice
Configuring and using NLog is easy as youll see in the next section. In addition, since configuration can be done in the
applications config file, its easy to use config transformations to have different settings for development, test and
production environments. This makes it easy to turn on and off logging completely for your unit tests for example. In
the next steps, you see how I can add logging to my WCF service project and then configure the web.config file to log
minimal information in production and lots of data during development. If you ever have the need to diagnose a
problem at run-time, just modify the configuration code and specify a different log level.
I started by installing NLog in my WCF service project using the following NuGet command:
I then added the following line of code at the top of the ContactManagerService class to declare and
instantiate a logger object:
Using the Logger instance I can now log with NLog using a single line of code. Note that NLog has multiple
methods for logging such as Warn, Trace, Error and more. Check out the documentation at https://github.com
/nlog/NLog/wiki for more information. The following code block shows some of the log messages you could add
to your service methods:
1 Install-Package NLog
1
2
3
4
5
6
7
8
namespace Spaanjaars.ContactManager45.Web.Wcf
{
public class ContactManagerService : IContactManagerService
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
// Other code here
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ContactManagerService : IContactManagerService
{
private readonly IPeopleRepository _peopleRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;

private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

public ContactManagerService(IPeopleRepository peopleRepository,
IUnitOfWorkFactory unitOfWorkFactory)
{
if (peopleRepository == null)
{
Logger.Error("peopleRepository is null.");
throw new ArgumentNullException("peopleRepository", "peopleRepository is null.");
}
if (unitOfWorkFactory == null)
{
Logger.Error("unitOfWorkFactory is null.");
throw new ArgumentNullException("unitOfWorkFactory", "unitOfWorkFactory is null.");
}
_peopleRepository = peopleRepository;
_unitOfWorkFactory = unitOfWorkFactory;
}

public PersonModel GetPerson(int id)
{
Logger.Trace("Getting person: {0}", id);
var person = _peopleRepository.FindById(id);
Logger.Trace("Person with ID: {0} is {1}null.", id, person == null ? "" : "not ");
return Mapper.Map(person, new PersonModel());
}
}
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 158 of 162
In this sample code I am using the Error method to log exception cases, and Trace to log additional information. This
way, an error like a missing repository can always be logged while the additional information is only logged when you
configure NLog to log trace message as well.
The next step is to add config information to the application to tell NLog what to log and where. NLog supports
three main ways to configure it: through its API (https://github.com/nlog/nlog/wiki/Configuration-API),
through an external config file and with configuration code embedded in the applications main file. For the
latter two solutions, check out https://github.com/nlog/nlog/wiki/Configuration-file. I prefer to embed the code
in my main configuration file as it makes it easier to use Web Config Transformations to generate different
versions of the file for different deployment targets. To enable logging, you can add something like the
following to the top of the config file
If you now call one of the service methods (for example, GetPerson) youll see something like this in the log file:
Since no exceptions are raised, you only see the Trace messages, If you disable that trace level by setting the
minLevel to Info, you wont see anything at all in the log file for normal operations, Exceptions are still logged
though; this is a great setting for a production server:
If you want to use the log file from your unit test project as well you need to add the NLog configuration code
to the unit test projects app.config file. In addition, because of the way unit tests are executed, you need to
supply an absolute path to the log file, like so:
The final tool I often use when building database-driven web applications is Red Gates SQL Compare, discussed next.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
</configSections>

<nlog xmlns=http://www.nlog-project.org/schemas/NLog.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="file" xsi:type="File" fileName="${basedir}/App_Data/Log.txt"
layout="${longdate} ${callsite} ${level} ${message} ${exception:format=tostring}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
1
2
3
4
2013-05-06 17:18:02.3084 Spaanjaars.ContactManager45.Web.Wcf.
ContactManagerService.GetPerson Trace Getting person: 40
2013-05-06 17:18:02.3535 Spaanjaars.ContactManager45.Web.Wcf
ContactManagerService.GetPerson Trace Person with ID: 40 is not null.
1 <logger name="*" minlevel="Info" writeTo="file" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
</configSections>
<nlog xmlns=http://www.nlog-project.org/schemas/NLog.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="file" xsi:type="File"
fileName="C:\Projects\Spaanjaars.ContactManagerV45\Main\Logs\WcfTests.txt"
layout="${longdate} ${callsite} ${level} ${message} ${exception:format=tostring}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
</configuration>
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 159 of 162
Using Red Gates SQL Compare to Update your Live Database
Earlier in this series I mentioned that I usually dont use EF migrations in a production environment. Often DBAs wont
grant permissions to your application to modify the database schema at run-time. Instead, when doing a deployment,
they typically want you to supply a SQL file with DDL (Data Definition Language) statements that update the database
to the latest schema. While you could use the command line options of EF Migrations to create those scripts, I usually
find it easier to compare the latest development database with the production environment using a tool like SQL
Compare from Red Gate
(12)
. Just like Data Generator, SQL Compare is a commercial tool with a price that starts
around 295. It also comes bundled in the SQL Developer Bundle and the SQL Toolbelt packages.
In order to compare the databases, you need access to both the source and target database from the machine that
runs SQL Compare. For a production environment that may not be feasible. In that case, its recommended to restore
a backup of production on your local or networked machine and use that for the compare operations.
To explain how to use SQL Compare, I added a new property called NickName to the Person class in the EF model:
I then ran my unit tests which in turn recreated the database so the Person table now also has a NickName column.
To perform a compare operation and script the changes, I started SQL Compare and then configured the source and
target databases. In Figure 10-4 you can see I am comparing two databases running on my local machine.
(13) See Links in this Document at the end for the full URL of this image.
Figure 10-4 Red Gate SQL Compare Configure Databases
By clicking Compare Now, SQL Compare will analyze both databases and then displays a window with the results,
shown in Figure 10-5:
1 public string NickName { get; set; }
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 160 of 162
(14) See Links in this Document at the end for the full URL of this image.
Figure 10-5 Red Gate SQL Compare Results
Notice how it picked up the new column, highlighted in the T-SQL section at the bottom. Next, I selected the People
table and then clicked Deployment Wizard on the main toolbar. This triggers a dialog that lets you choose between
generating a .sql script file (that can be used to update the target database at a later stage) or immediately update
the target database. The former case is useful if you need to run the SQL script on another database or on multiple
databases, or if you dont have direct access to the target database. The Deploy Using SQL Compare option will
directly modify the target database, bringing the two databases in sync.
This example is somewhat contrived as its a relatively simple change to the database. You wont be able to make
some complex changes such as adding a non-nullable column to an existing table as SQL Compare currently has no
way to specify a default value to use in the upgrade process. As a solution you could add a default value to the column
in the source database and then run the Deployment Wizard. Alternatively, you can let the tool generate the SQL file
for the update process and then manually update it to supply a default value. Hopefully Red Gate adds support for
scenarios like this to SQL Compare in a future release.
Summary
In this article youve seen a number of extensions you could add to the sample application as well as number of tools
and frameworks that I often use when building database-driven, N-layered web applications.
Although Ive tried to make the sample solution as rich as possible, there are a number of features I did not include. In
this article, I briefly mentioned a few and provided pointers on how to implement them yourself.
The article then discussed a few tools to create a great set of sample data (Data Generator), profile your Entity
Framework queries (Entity Framework Profiler) and generate scripts to update production databases (SQL Compare). I
also discussed the NLog framework that enables you to log information from your application during run-time in order
to find and diagnose issues with your application.
This article also includes the series Building N-Layered Applications with ASP.NET 4.5. Over the past 10 articles, youve
seen how to build an N-layered application using Visual Studio 2012 and (ASP).NET 4.5. In the first five articles youve
seen how to design and set up your solution, how to make your solution unit testable, how to design your applications
domain model and how to build an entity framework implementation of the IRepository interface to work with data
from a SQL Server database in the frontend application.
Article 6 to 9 discussed various ways to implement a frontend. These articles showed you how to build ASP.NET MVC 4
and ASP.NET Web Forms 4.5 frontends, as well as a WCF service application and a command line tool to import
existing data. Each of these frontends have their own requirements and challenges which results in different
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 161 of 162
implementations of using the same repository layer in the solution.
The series closed off with a quick look at some of the tools that come in handy when building database driven
applications.
I hope you enjoyed reading the series as much as I enjoyed writing it. During the writing process I learned a ton of
new things on all the different technologies I am describing in these articles which in turn enabled me to refine the
processes and techniques I am using in my clients applications. I do realize that this article and concepts are just a
point in time. The software landscape changes rapidly so concepts that make sense today might be outdated
tomorrow. I wont be updating this series (much) over the coming time but I do look forward to writing an updated
series in a year or two, using techniques and technologies that are current by then.
If you have any comments or questions about this article series or the sample solution, post them at the end of the
article that deals with your question or get in touch with me through the Contact
(15)
page.
Thanks for reading, and happy N-layering!
Links in this Document
(1) http://imar.spaanjaars.com/481/n-layered-web-applications-with-aspnet-35-part-6-security
(2) http://www.red-gate.com/products/sql-development/sql-data-generator/
(3) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part10
/Figure10-1_Red_Gate_SQL_Data_Generator.png
(4) http://www.hibernatingrhinos.com/products/EFProf
(5) http://www.hibernatingrhinos.com/products/efprof/learn/alert/selectnplusone
(6) http://www.hibernatingrhinos.com/products/UberProf
(7) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part10/Figure10-2_EF_Profiler.png
(8) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part10/Figure10-3_EF_Profiler_Showing_Issues.png
(9) http://logging.apache.org/log4net/
(10) http://msdn.microsoft.com/en-us/library/ff647183.aspx
(11) http://nlog-project.org/
(12) http://www.red-gate.com/products/sql-development/sql-compare/
(13) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part10/Figure10-4_Red_Gate_SQL_Compare.png
(14) Image: http://imar.spaanjaars.com/Images/Articles/NLayer45/Part10
/Figure10-5_Red_Gate_SQL_Compare_Results.png
(15) http://imar.spaanjaars.com/contact
ASP.NET N-Layered Applications - Extensions, Tools and Wrapping Up (Part 10)
Imar Spaanjaars - http://imar.spaanjaars.com - 2013 Page 162 of 162

You might also like