Developing web apps using ASP.NET MVC 3, Razor and EF Code First - Part 1
In this post, I will demonstrate web application development using ASP. NET MVC 3, Razor and EF code First. This post will also cover Dependency Injection using Unity 2.0 and generic Repository and Unit of Work for EF Code First.You can download the source code from http://efmvc.codeplex.com.The following frameworks will be used for this step by step tutorial.
- ASP.NET MVC 3
- EF Code First CTP 5
- Unity 2.0
Define Domain Model
Let’s create domain model for our simple web application
Category class
- public class Category
- {
- public int CategoryId { get; set; }
- [Required(ErrorMessage = "Name Required")]
- [StringLength(25, ErrorMessage = "Must be less than 25 characters")]
- public string Name { get; set;}
- public string Description { get; set; }
- public virtual ICollection<Expense> Expenses { get; set; }
- }
Expense class
- public class Expense
- {
- public int ExpenseId { get; set; }
- public string Transaction { get; set; }
- public DateTime Date { get; set; }
- public double Amount { get; set; }
- public int CategoryId { get; set; }
- public virtual Category Category { get; set; }
- }
We have two domain entities - Category and Expense. A single category contains a list of expense transactions and every expense transaction should have a Category. We want to develop a simple expense tracking application and update expense transactions with a particular expense category. In this post, we will be focusing on CRUD operations for the entity Category and will be working on the Expense entity with a View Model object in the later post. And the source code for this application will be refactored over time.
The above entities are very simple POCO (Plain Old CLR Object) classes and the entity Category is decorated with validation attributes in the System.ComponentModel.DataAnnotations namespace. Now we want to use these entities for defining model objects for the Entity Framework 4. Using the Code First approach of Entity Framework, we can first define the entities by simply writing POCO classes without any coupling with any API or database library. This approach lets you focus on domain model which will enable Domain-Driven Development for applications. EF code first support is currently enabled with a separate API that is runs on top of the Entity Framework 4. EF Code First is reached CTP 5 when I am writing this article.
Creating Context Class for Entity Framework
We have created our domain model and let’s create a class in order to working with Entity Framework Code First. For this, you have to download EF Code First CTP 5 and add reference to the assembly EntitFramework.dll. You can also use NuGet to download add reference to EEF Code First.
- public class MyFinanceContext : DbContext
- {
- public MyFinanceContext() : base("MyFinance") { }
- public DbSet<Category> Categories { get; set; }
- public DbSet<Expense> Expenses { get; set; }
- }
The above class MyFinanceContext is derived from DbContext that can connect your model classes to a database. The MyFinanceContext class is mapping our Category and Expense class into database tables
Categories and Expenses using DbSet<TEntity> where TEntity is any POCO class. When we are running the application at first time, it will automatically create the database. EF code-first look for a connection string in web.config or app.config that has the same name as the dbcontext class. If it is not find any connection string with the convention, it will automatically create database in local SQL Express database by default and the name of the database will be same name as the dbcontext class. You can also define the name of database in constructor of the the dbcontext class.
We don’t have to use any XML based mapping files or Fluent interface for mapping between our model and database. The model classes of Code First are working on the basis of conventions and we can also use a fluent API to refine our model. The convention for primary key is ‘Id’ or ‘<class name>Id’. If primary key properties are detected with type ‘int’, ‘long’ or ‘short’, they will automatically registered as identity columns in the database by default. Primary key detection is not case sensitive. We can define our model classes with validation attributes in the System.ComponentModel.DataAnnotations namespace and it automatically enforces validation rules when a model object is updated or saved.
Generic Repository for EF Code First
We have created model classes and dbcontext class. Now we have to create generic repository pattern for data persistence with EF code first. If you don’t know about the repository pattern, checkout Martin Fowler’s article on Repository
Let’s create a generic repository to working with DbContext and DbSet generics.
- public interface IRepository<T> where T : class
- {
- void Add(T entity);
- void Delete(T entity);
- T GetById(long Id);
- T Get(Func<T, Boolean> where);
- IEnumerable<T> GetAll();
- IEnumerable<T> GetMany(Func<T, bool> where);
- }
RepositoryBasse – Generic Repository class
- public abstract class RepositoryBase<T> where T : class
- {
- private MyFinanceContext dataContext;
- private readonly IDbSet<T> dbset;
- protected RepositoryBase(IDatabaseFactory databaseFactory)
- {
- DatabaseFactory = databaseFactory;
- dbset = DataContext.Set<T>();
- }
- protected IDatabaseFactory DatabaseFactory
- {
- get; private set;
- }
- protected MyFinanceContext DataContext
- {
- get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
- }
- public virtual void Add(T entity)
- {
- dbset.Add(entity);
- }
- public virtual void Delete(T entity)
- {
- dbset.Remove(entity);
- }
- public virtual T GetById(long id)
- {
- return dbset.Find(id);
- }
- public virtual IEnumerable<T> GetAll()
- {
- return dbset.ToList();
- }
- public virtual IEnumerable<T> GetMany(Func<T, bool> where)
- {
- return dbset.Where(where).ToList();
- }
- public T Get(Func<T, Boolean> where)
- {
- return dbset.Where(where).FirstOrDefault<T>();
- }
- }
DatabaseFactory class
- public class DatabaseFactory : Disposable, IDatabaseFactory
- {
- private MyFinanceContext dataContext;
- public MyFinanceContext Get()
- {
- return dataContext ?? (dataContext = new MyFinanceContext());
- }
- protected override void DisposeCore()
- {
- if (dataContext != null)
- dataContext.Dispose();
- }
- }
Please note that the generic repository and related classes are just a basic version and will be completely refactored later.
Unit of Work
If you are new to Unit of Work pattern, checkout Fowler’s article on Unit of Work . According to Martin Fowler, the Unit of Work pattern "maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems."
Let’s create a class for handling Unit of Work
- public interface IUnitOfWork
- {
- void Commit();
- }
UniOfWork class
- public class UnitOfWork : IUnitOfWork
- {
- private readonly IDatabaseFactory databaseFactory;
- private MyFinanceContext dataContext;
- public UnitOfWork(IDatabaseFactory databaseFactory)
- {
- this.databaseFactory = databaseFactory;
- }
- protected MyFinanceContext DataContext
- {
- get { return dataContext ?? (dataContext = databaseFactory.Get()); }
- }
- public void Commit()
- {
- DataContext.Commit();
- }
- }
The Commit method of the UnitOfWork will call the commit method of MyFinanceContext class and it will execute the SaveChanges method of DbContext class.
Repository class for Category
In this post, we will be focusing on the persistence against Category entity and will working on other entities in later post. Let’s create a repository for handling CRUD operations for Category using derive from a generic Repository RepositoryBase<T>.
- public class CategoryRepository: RepositoryBase<Category>, ICategoryRepository
- {
- public CategoryRepository(IDatabaseFactory databaseFactory)
- : base(databaseFactory)
- {
- }
- }
- public interface ICategoryRepository : IRepository<Category>
- {
- }
If we need additional methods than generic repository for the Category, we can define in the CategoryRepository.
Dependency Injection using Unity 2.0
If you are new to Inversion of Control/ Dependency Injection or Unity, please have a look on my articles at http://weblogs.asp.net/shijuvarghese/archive/tags/IoC/default.aspx. I want to create a custom lifetime manager for Unity to store container in the current HttpContext.
- public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
- {
- public override object GetValue()
- {
- return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
- }
- public override void RemoveValue()
- {
- HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
- }
- public override void SetValue(object newValue)
- {
- HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
- }
- public void Dispose()
- {
- RemoveValue();
- }
- }
Let’s create controller factory for Unity in the ASP.NET MVC 3 application.
- public class UnityControllerFactory : DefaultControllerFactory
- {
- IUnityContainer container;
- public UnityControllerFactory(IUnityContainer container)
- {
- this.container = container;
- }
- protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
- {
- IController controller;
- if (controllerType == null)
- throw new HttpException(
- 404, String.Format(
- "The controller for path '{0}' could not be found" +
- "or it does not implement IController.",
- reqContext.HttpContext.Request.Path));
- if (!typeof(IController).IsAssignableFrom(controllerType))
- throw new ArgumentException(
- string.Format(
- "Type requested is not a controller: {0}",
- controllerType.Name),
- "controllerType");
- try
- {
- controller= container.Resolve(controllerType) as IController;
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(String.Format(
- "Error resolving controller {0}",
- controllerType.Name), ex);
- }
- return controller;
- }
- }
Configure contract and concrete types in Unity
Let’s configure our contract and concrete types in Unity for resolving our dependencies.
- private void ConfigureUnity()
- {
- //Create UnityContainer
- IUnityContainer container = new UnityContainer()
- .RegisterType<IDatabaseFactory, DatabaseFactory>(new HttpContextLifetimeManager<IDatabaseFactory>())
- .RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>())
- .RegisterType<ICategoryRepository, CategoryRepository>(new HttpContextLifetimeManager<ICategoryRepository>());
- //Set container for Controller Factory
- ControllerBuilder.Current.SetControllerFactory(
- new UnityControllerFactory(container));
- }
In the above ConfigureUnity method, we are registering our types onto Unity container with custom lifetime manager HttpContextLifetimeManager. Let’s call ConfigureUnity method in the Global.asax.cs for set controller factory for Unity and configuring the types with Unity.
- protected void Application_Start()
- {
- AreaRegistration.RegisterAllAreas();
- RegisterGlobalFilters(GlobalFilters.Filters);
- RegisterRoutes(RouteTable.Routes);
- ConfigureUnity();
- }
Developing web application using ASP.NET MVC 3
We have created our domain model for our web application and also have created repositories and configured dependencies with Unity container. Now we have to create controller classes and views for doing CRUD operations against the Category entity.
Let’s create controller class for Category
Category Controller
- public class CategoryController : Controller
- {
- private readonly ICategoryRepository categoryRepository;
- private readonly IUnitOfWork unitOfWork;
- public CategoryController(ICategoryRepository categoryRepository, IUnitOfWork unitOfWork)
- {
- this.categoryRepository = categoryRepository;
- this.unitOfWork = unitOfWork;
- }
- public ActionResult Index()
- {
- var categories = categoryRepository.All();
- return View(categories);
- }
- [HttpGet]
- public ActionResult Edit(int id)
- {
- var category = categoryRepository.GetById(id);
- return View(category);
- }
- [HttpPost]
- public ActionResult Edit(int id, FormCollection collection)
- {
- var category = categoryRepository.GetById(id);
- if (TryUpdateModel(category))
- {
- unitOfWork.Commit();
- return RedirectToAction("Index");
- }
- else return View(category);
- }
- [HttpGet]
- public ActionResult Create()
- {
- var category = new Category();
- return View(category);
- }
- [HttpPost]
- public ActionResult Create(Category category)
- {
- if (!ModelState.IsValid)
- {
- return View("Create", category);
- }
- categoryRepository.Add(category);
- unitOfWork.Commit();
- return RedirectToAction("Index");
- }
- [HttpPost]
- public ActionResult Delete(int id)
- {
- var category = categoryRepository.GetById(id);
- categoryRepository.Delete(category);
- unitOfWork.Commit();
- var categories = categoryRepository.All();
- return PartialView("CategoryList", categories);
- }
- }
Creating Views in Razor
Now we are going to create views in Razor for our ASP.NET MVC 3 application. Let’s create a partial view CategoryList.cshtml for listing category information and providing link for Edit and Delete operations.
CategoryList.cshtml
- @using MyFinance.Helpers;
- @using MyFinance.Domain;
- @model IEnumerable<Category>
- <table>
- <tr>
- <th>Actions</th>
- <th>Name</th>
- <th>Description</th>
- </tr>
- @foreach (var item in Model) {
- <tr>
- <td>
- @Html.ActionLink("Edit", "Edit",new { id = item.CategoryId })
- @Ajax.ActionLink("Delete", "Delete", new { id = item.CategoryId }, new AjaxOptions { Confirm = "Delete Expense?", HttpMethod = "Post", UpdateTargetId = "divCategoryList" })
- </td>
- <td>
- @item.Name
- </td>
- <td>
- @item.Description
- </td>
- </tr>
- }
- </table>
- <p>
- @Html.ActionLink("Create New", "Create")
- </p>
The delete link is providing Ajax functionality using the Ajax.ActionLink. This will call an Ajax request for Delete action method in the CategoryCotroller class. In the Delete action method, it will return Partial View CategoryList after deleting the record. We are using CategoryList view for the Ajax functionality and also for Index view using for displaying list of category information.
Let’s create Index view using partial view CategoryList
Index.chtml
- @model IEnumerable<MyFinance.Domain.Category>
- @{
- ViewBag.Title = "Index";
- }
- <h2>Category List</h2>
- <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
- <div id="divCategoryList">
- @Html.Partial("CategoryList", Model)
- </div>
We can call the partial views using Html.Partial helper method. Now we are going to create View pages for insert and update functionality for the Category.
Both view pages are sharing common user interface for entering the category information. So I want to create an EditorTemplate for the Category information. We have to create the EditorTemplate with the same name of entity object so that we can refer it on view pages using @Html.EditorFor(model => model) . So let’s create template with name Category.
Category.cshtml
- @model MyFinance.Domain.Category
- <div class="editor-label">
- @Html.LabelFor(model => model.Name)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Name)
- @Html.ValidationMessageFor(model => model.Name)
- </div>
- <div class="editor-label">
- @Html.LabelFor(model => model.Description)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Description)
- @Html.ValidationMessageFor(model => model.Description)
- </div>
Let’s create view page for insert Category information
- @model MyFinance.Domain.Category
- @{
- ViewBag.Title = "Save";
- }
- <h2>Create</h2>
- <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
- <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
- @using (Html.BeginForm()) {
- @Html.ValidationSummary(true)
- <fieldset>
- <legend>Category</legend>
- @Html.EditorFor(model => model)
- <p>
- <input type="submit" value="Create" />
- </p>
- </fieldset>
- }
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
ViewStart file
In Razor views, we can add a file named _viewstart.cshtml in the views directory and this will be shared among the all views with in the Views directory. The below code in the _viewstart.cshtml, sets the Layout page for every Views in the Views folder.
- @{
- Layout = "~/Views/Shared/_Layout.cshtml";
- }
Source Code
You can download the source code from http://efmvc.codeplex.com/ . The source will be refactored on over time.
Summary
In this post, we have created a simple web application using ASP.NET MVC 3 and EF Code First. We have discussed on technologies and practices such as ASP.NET MVC 3, Razor, EF Code First, Unity 2, generic Repository and Unit of Work. In my later posts, I will modify the application and will be discussed on more things. Stay tuned to my blog for more posts on step by step application building.