Creating Self Hosted Asp.Net WebAPI with CURD operations in Visual Studio 2010


Introduction

I have been writing a lot over WebAPIs in my Learning WebAPI series, but one crucial topic that I missed was hosting an asp.net WebAPI .

Hosting a WebAPI in IIS is pretty straight forward and is more similar to how you host a typical asp.net web application.In this article, I’ll explain how we can host a WebAPI in another process independent of IIS.

I’ll explain how to quickly create a WebAPI having CURD operations with Entity Framework 4.0 and then host it in an independent server.I’ll call the service endpoints through a console application acting as a client. You can use any client to check the service end points and verify their functionality. I’ll try to explain the topic with practical implementations , create a service and a test client in Visual Studio 2010 around target framework as .Net Framework 4.0.

Continue reading “Creating Self Hosted Asp.Net WebAPI with CURD operations in Visual Studio 2010”

RESTful Day #7: Unit Testing and Integration Testing in WebAPI using NUnit and Moq framework (Part 1)


Source Code at GitHub

Introduction

We have been learning a lot in WebAPI. We covered almost all the techniques required to build a robust and a full stack REST service using ASP.NET WebAPI, from creating a service to making it a secure and ready-to-use boilerplate with enterprise level applications. In this article, we’ll learn on how to focus on test driven development and write unit tests for our service endpoints and business logic. I’ll use NUnit and Moq framework to write test cases for business logic layer and controller methods. I’ll cover less theory and focus more on practical implementations on how to use these frameworks to write unit tests. I have segregated the article into two parts. The first part focusses on testing business logic and class libraries created as BusinessServices in our code base. The second part will focus on testing a Web API. The purpose of segregation is simple; the scope of this article is very large and may turn up into a very large post which would be not easy to read in one go.

Roadmap

The following is the roadmap I have setup to learn WebAPI step by step:

I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how to do it.

Unit Tests

“Unit tests allow you to make big changes to code quickly. You know it works now because you’ve run the tests, when you make the changes you need to make, you need to get the tests working again. This saves hours.” I got this from a post at stack overflow, and I completely agree to this statement.
A good unit test helps a developer to understand his code and (most importantly) the business logic. Unit tests help to understand all the aspects of business logic, right from the desired input and output to the conditions where the code can fail. A code having well written unit tests have less chances to fail provided the unit tests cover all the test cases required to execute.

NUnit

There are various frameworks available for Unit tests. NUnit is the one that I prefer. NUnit gels well with .NET and provides flexibility to write unit tests without hassle. It has meaningful and self-explanatory properties and class names that help developers write the tests in an easy way. NUnit provides an easy to use interactive GUI where you can run the tests and get the details. It shows the number of tests passed or failed in a beautiful fashion and also gives the stack trace in if any test fails, thereby enabling you to perform the first level of debugging at the GUI itself. I suggest downloading and installing NUnit on your machine for running the tests. We’ll use NUnit GUI after we write all the tests. I normally use inbuilt GUI of NUnit provided by ReSharper integrated in my Visual Studio. However, I have suggested you use NUnit GUI to run the tests since ReSharper is a paid library and only few developers may have it integrated. Since we are using Visual Studio 2010, we need to use the older version of NUnit i.e. 2.6.4. You can download and run the .msi and install on your machine following this URL.
Once you finish installation, you’ll see NUnit installed in your installed items on your machine as shown in below image:

Moq Framework

Moq is a simple and straightforward library to mock the objects in C#. We can mock data, repositories, classes, and instances with the help of mock library. So when we write unit tests, we do not execute them on the actual class instances, but instead perform in-memory unit testing by making a proxy of class objects. Like NUnit, Moq library classes are also easy to use and understand. Almost all of its methods, classes and interface names are self-explanatory.
The following is the list taken from Wikipedia on why to use mock objects
  • The object supplies non-deterministic results (e.g., the current time or the current temperature);
  • Has states that are not easy to create or reproduce (e.g., a network error);
  • Is slow (e.g., a complete database, which would have to be initialized before the test);
  • Does not yet exist or may change behavior;
  • Would have to include information and methods exclusively for testing purposes (and not for its actual task).
So whatever test we write, we actually execute that on test data and proxy objects i.e. not the instances of real classes. We’ll use Moq to mock data and repositories so that we do not hit the database again and again for executing unit tests. You can read more about Moq in this article.

Setup Solution

I’ll use this article to explain how to write unit tests for business logic i.e. covering our business logic layer and for WebAPI controllers. The scope of Unit tests should not be only limited to business logic or endpoints, but should be spread over all publically exposed logics like filters and handlers as well. Well written unit tests should cover almost all the code. One can track the code coverage through some of the tools available online. We’ll not test filters and common classes, but will focus on controllers and business logic layer and get an idea of how to proceed with unit tests. I’ll use the same source code that we used until Day# 6 of the series and will proceed with the latest code base that we got out of last article of the series. The code base is available for download with this post. When you take the code base from my last article and open it in Visual Studio, you’ll see the project structure something like as shown in below image:
IUnitOfWork is the new interface that I have added to facilitate interface driven development. It helps in mocking objects and improved structure and readability. Just open Visual Studio and add a new interface named IUnitOfWork under UnitOfWork folder in DataModel project and define the properties used in UnitOfWork class as shown below:
Now, go to the UnitOfWork class and inherit that class using this interface, so UnitOfWork class becomes something like this
#region Using Namespaces...

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.Data.Entity.Validation;
using DataModel.GenericRepository;

#endregion

namespace DataModel.UnitOfWork
{
    /// <summary>
    /// Unit of Work class responsible for DB transactions
    /// </summary>
    public class UnitOfWork : IDisposable, IUnitOfWork
    {
        #region Private member variables...

        private readonly WebApiDbEntities _context = null;
        private GenericRepository _userRepository;
        private GenericRepository _productRepository;
        private GenericRepository _tokenRepository;
        #endregion

        public UnitOfWork()
        {
            _context = new WebApiDbEntities();
        }

        #region Public Repository Creation properties...

        /// <summary>
        /// Get/Set Property for product repository.
        /// </summary>
        public GenericRepository ProductRepository
        {
            get
            {
                if (this._productRepository == null)
                    this._productRepository = new GenericRepository(_context);
                return _productRepository;
            }
        }

        /// <summary>
        /// Get/Set Property for user repository.
        /// </summary>
        public GenericRepository UserRepository
        {
            get
            {
                if (this._userRepository == null)
                    this._userRepository = new GenericRepository(_context);
                return _userRepository;
            }
        }

        /// <summary>
        /// Get/Set Property for token repository.
        /// </summary>
        public GenericRepository TokenRepository
        {
            get
            {
                if (this._tokenRepository == null)
                    this._tokenRepository = new GenericRepository(_context);
                return _tokenRepository;
            }
        }
        #endregion

        #region Public member methods...
        /// <summary>
        /// Save method.
        /// </summary>
        public void Save()
        {
            try
            {
                _context.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {

                var outputLines = new List();
                foreach (var eve in e.EntityValidationErrors)
                {
                    outputLines.Add(string.Format("{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        outputLines.Add(string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
                    }
                }
                System.IO.File.AppendAllLines(@"C:\errors.txt", outputLines);

                throw e;
            }

        }

        #endregion

        #region Implementing IDiosposable...

        #region private dispose variable declaration...
        private bool disposed = false; 
        #endregion

        /// <summary>
        /// Protected Virtual Dispose method
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    Debug.WriteLine("UnitOfWork is being disposed");
                    _context.Dispose();
                }
            }
            this.disposed = true;
        }

        /// <summary>
        /// Dispose method
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        } 
        #endregion
    }
}
So, now all the interface members defined in IUnitOfWork are implemented in UnitOfWork class:
public interface IUnitOfWork
    {
        #region Properties
        GenericRepository ProductRepository { get; }
        GenericRepository UserRepository { get; }
        GenericRepository TokenRepository { get; } 
        #endregion
        
        #region Public methods
        /// <summary>
        /// Save method.
        /// </summary>
        void Save(); 
        #endregion
    }
Doing this will not change the functionality of our existing code, but we also need to update the business services with this Interface. We’ll pass this IUnitOfWork interface instance inside services constructors instead of directly using UnitOfWork class.
private readonly IUnitOfWork _unitOfWork;

public ProductServices(IUnitOfWork unitOfWork)
{
    _unitOfWork = unitOfWork;
}
So our User service, Token service and product service constructors becomes as shown below,

Product Service

User Service

Token Service

Testing Business Services

We’ll start writing unit tests for BusinessServices project.

Step 1: Test Project

Add a simple class library in the existing Visual Studio and name it BusinessServices.Tests. Open Tools->Library Packet Manager->Packet manager Console to open the package manager console window. We need to install come packages before we proceed.

Step 2: Install NUnit package

In package manager console, select BusinessServices.Tests as default project and write command “Install-Package NUnit –Version 2.6.4“. If you do not mention the version, the PMC (Package manage Console) will try to download the latest version of NUnit nugget package but we specifically need 2.6.4, so we need to mention the version. Same applies to when you try to install any such package from PMC
After successfully installed, you can see the DLL reference in project references i.e. nunit.framework,

Step 3: Install Moq framework

Install the framework on the same project in the similar way as explained in Step 2. Write command “Install-Package Moq” .Here we use latest version of Moq
Therefore adding the DLL

Step 4: Install Entity Framework

Install-Package EntityFramework –Version 5.0.0

Step 5: Install AutoMapper

Install-Package AutoMapper –Version 3.3.1
Our package.config i.e. automatically added in the project looks like,
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AutoMapper" version="3.3.1" targetFramework="net40" />
  <package id="EntityFramework" version="5.0.0" targetFramework="net40" />
  <package id="Moq" version="4.2.1510.2205" targetFramework="net40" />
  <package id="NUnit" version="2.6.4" targetFramework="net40" />
</packages>

Step 6: References

Add references of DataModel, BusinessServices, BusinessEntities project to this project.

TestHelper

We will require few helper files that would be needed in BusinessServices.Tests project and in our WebAPI.Tests project that we’ll create later. To place all the helper files, I have created one more class library project named TestHelper. Just right click the solution and add new project named TestHelper and add a class namedDataInitializer.cs into it. This class contains three simple methods to fetch i.e. User’s, Product’s and Token’s dummy data. You can use the following code as the class implementation:
using System;
using System.Collections.Generic;
using DataModel;

namespace TestsHelper
{
/// <summary>
/// Data initializer for unit tests
/// </summary>
public class DataInitializer
{
/// <summary>
/// Dummy products
/// </summary>
/// <returns></returns>
public static List GetAllProducts()
{
var products = new List
{
new Product() {ProductName = "Laptop"},
new Product() {ProductName = "Mobile"},
new Product() {ProductName = "HardDrive"},
new Product() {ProductName = "IPhone"},
new Product() {ProductName = "IPad"}
};
return products;
}

/// <summary>
/// Dummy tokens
/// </summary>
/// <returns></returns>
public static List GetAllTokens()
{
var tokens = new List
{
new Token()
{
AuthToken = "9f907bdf-f6de-425d-be5b-b4852eb77761",
ExpiresOn = DateTime.Now.AddHours(2),
IssuedOn = DateTime.Now,
UserId = 1
},
new Token()
{
AuthToken = "9f907bdf-f6de-425d-be5b-b4852eb77762",
ExpiresOn = DateTime.Now.AddHours(1),
IssuedOn = DateTime.Now,
UserId = 2
}
};

return tokens;
}

/// <summary>
/// Dummy users
/// </summary>
/// <returns></returns>
public static List GetAllUsers()
{
var users = new List
{
new User()
{
UserName = "akhil",
Password = "akhil",
Name = "Akhil Mittal",
},
new User()
{
UserName = "arsh",
Password = "arsh",
Name = "Arsh Mittal",
},
new User()
{
UserName = "divit",
Password = "divit",
Name = "Divit Agarwal",
}
};

return users;
}

}
}
In the above class GetAllUsers() fetches dummy data for users, GetAllProducts() fetches dummy data for Products and GetAllTokens() method fetches dummy data for Tokens. So now, our solution has two new projects as shown below:
Add DataModel project reference to TestHelper project and TestHelper project reference to BusinessServices.Tests project.

ProductService Tests

We’ll start with setting up the project and setting up the pre-requisites for tests and gradually move on to actual tests.

Tests Setup

We’ll proceed with creating ProductServices tests. Add a new class named ProductServicesTests.cs in BusinessServices.Tests project.
Declare variables
Define the private variables that we’ll use in the class to write tests,
#region Variables
private IProductServices _productService;
private IUnitOfWork _unitOfWork;
private List _products;
private GenericRepository _productRepository;
private WebApiDbEntities _dbEntities;
#endregion
Variable declarations are self-explanatory where _productService will hold mock for ProductServices,_unitOfWork for UnitOfWork class, _products will hold dummy products from DataInitializer class of TestHelper project, _productRepository and _dbEntities holds mock for Product Repository and WebAPIDbEntities from DataModel project respectively.
Write Test Fixture Setup
Test fixture setup is written as a onetime setup for all the tests. It is like a constructor in terms of classes. When we start executing setup, this is the first method to be executed. In this method we’ll populate the dummy products data and decorate this method with the [TestFixtureSetUp] attribute at the top that tells compiler that the particular method is a TestFixtureSetup. [TestFixtureSetUp] attribute is the part of NUnit framework, so include it in the class as a namespace i.e. using NUnit.Framework;. Following is the code forTestFixtureSetup.
#region Test fixture setup

 /// <summary>
 /// Initial setup for tests
 /// </summary>
 [TestFixtureSetUp]
 public void Setup()
 {
     _products = SetUpProducts();
 }

 #endregion

private static List SetUpProducts()
 {
     var prodId = new int();
     var products = DataInitializer.GetAllProducts();
     foreach (Product prod in products)
         prod.ProductId = ++prodId;
     return products;

 }
SetUpproducts() method fetches products from DataInitializer class and not from database. It also and assigns a unique id to each product by iterating them. The result data is assigned to _products list to be used in setting up mock repository and in every individual test for comparison of actual vs resultant output.
Write Test Fixture Tear Down
Unlike TestFixtureSetup, tear down is used to de-allocate or dispose the objects. It also executes only one time when all the tests execution ends. In our case we’ll use this method to nullify _products instance. The attribute used for Test fixture tear down is [TestFixtureTearDown].
Following is the code for teardown.
#region TestFixture TearDown.

 /// <summary>
 /// TestFixture teardown
 /// </summary>
 [TestFixtureTearDown]
 public void DisposeAllObjects()
 {
     _products = null;
 }

 #endregion
Note that we have till now not written any unit test.
Write Test Setup
TestFixtureSetUp is a onetime run process whereas [SetUp] marked method is executed after each test. Each test should be independent and should be tested with a fresh set of input. Setup helps us to re-initialize data for each test. Therefore, all the required initialization for tests are written in this particular method marked with the [SetUp] attribute. I have written a few methods and initialized the private variables in this method. These lines of code execute after each test ends, so that individual tests do not depend on any other written tests and do not get hampered with other tests pass or fail status. The code for Setup:
#region Setup
/// <summary>
/// Re-initializes test.
/// </summary>
[SetUp]
public void ReInitializeTest()
{
    _dbEntities = new Mock().Object;
    _productRepository = SetUpProductRepository();
    var unitOfWork = new Mock();
    unitOfWork.SetupGet(s => s.ProductRepository).Returns(_productRepository);
    _unitOfWork = unitOfWork.Object;
    _productService = new ProductServices(_unitOfWork);
}

#endregion
We make use of Mock framework in this method to mock the private variable instances. Like for _dbEntitieswe write _dbEntities = new Mock().Object;. This means that we are mockingWebDbEntities class and getting its proxy object. Mock class is the class from Moq framework, so include the respective namespace using Moq; in the class
Write Test Tear down
Like test, Setup runs after every test. Similarly, Test [TearDown] is invoked after every test execution is complete. You can use tear down to dispose and nullify the objects that are initialized while setup. The method for tear down should be decorated with the [TearDown] attribute. The following is the test tear down implementation.
/// <summary>
/// Tears down each test data
/// </summary>
[TearDown]
public void DisposeTest()
{
    _productService = null;
    _unitOfWork = null;
    _productRepository = null;
    if (_dbEntities != null)
        _dbEntities.Dispose();
}
Mocking Repository
I talked about mocking repository for the entities. I have created a method SetUpProductRepository() to mock Product Repository and assign it to _productrepository in ReInitializeTest() method.
private GenericRepository SetUpProductRepository()
{

// Initialise repository
var mockRepo = new Mock<GenericRepository>(MockBehavior.Default, _dbEntities);

// Setup mocking behavior
mockRepo.Setup(p => p.GetAll()).Returns(_products);

mockRepo.Setup(p => p.GetByID(It.IsAny()))
.Returns(new Func(
id => _products.Find(p => p.ProductId.Equals(id))));

mockRepo.Setup(p => p.Insert((It.IsAny())))
.Callback(new Action(newProduct =>
{
dynamic maxProductID = _products.Last().ProductId;
dynamic nextProductID = maxProductID + 1;
newProduct.ProductId = nextProductID;
_products.Add(newProduct);
}));

mockRepo.Setup(p => p.Update(It.IsAny()))
.Callback(new Action(prod =>
{
var oldProduct = _products.Find(a => a.ProductId == prod.ProductId);
oldProduct = prod;
}));

mockRepo.Setup(p => p.Delete(It.IsAny()))
.Callback(new Action(prod =>
{
var productToRemove =
_products.Find(a => a.ProductId == prod.ProductId);

if (productToRemove != null)
_products.Remove(productToRemove);
}));

// Return mock implementation object
return mockRepo.Object;
}
Here we mock all the required methods of Product Repository to get the desired data from _products object and not from actual database.
The single line of code
var mockRepo = new Mock<GenericRepository>(MockBehavior.Default, _dbEntities);
mocks the Generic Repository for Product and mockRepo.Setup() mocks the repository methods by passing relevant delegates to the method.
Initialize UnitOfWork and Service
I have written following lines of code in ReInitializeTest() method i.e. our setup method,
var unitOfWork = new Mock();
unitOfWork.SetupGet(s => s.ProductRepository).Returns(_productRepository);
_unitOfWork = unitOfWork.Object;
_productService = new ProductServices(_unitOfWork);
Here you can see that I am trying to mock the UnitOfWork instance and forcing it to perform all its transactions and operations on _productRepository that we have mocked earlier. This means that all the transactions will be limited to the mocked repository and the actual database or the actual repository will not be touched. Same goes for service as well; we are initializing product Services with this mocked _unitOfWork. So when we use_productService in actual tests, it actually works on mocked UnitOfWork and test data only.
All set now and we are ready to write unit tests for ProductService. We’ll write test to perform all the CRUD operations that are part of ProductService.

1. GetAllProductsTest ()

Our ProductService in BusinessServices project contains a method named GetAllProducts (), following is the implementation,
public IEnumerable GetAllProducts()
{
var products = _unitOfWork.ProductRepository.GetAll().ToList();
if (products.Any())
{
Mapper.CreateMap();
var productsModel = Mapper.Map<List, List>(products);
return productsModel;
}
return null;
}
We see here, that this method fetches all the available products from the database, maps the database entity to our custom BusinessEntities.ProductEntity and returns the list of custom BusinessEntities.ProductEntity. It returns null if no products are found.
To start writing a test method, you need to decorate that test method with [Test] attribute of NUnit framework. This attribute specifies that particular method is a Unit Test method.
The following is the unit test method I have written for the above mentioned business service method:
[Test]
public void GetAllProductsTest()
{
var products = _productService.GetAllProducts();
var productList =
products.Select(
productEntity =>
new Product {ProductId = productEntity.ProductId, ProductName = productEntity.ProductName}).ToList();
var comparer = new ProductComparer();
CollectionAssert.AreEqual(
productList.OrderBy(product => product, comparer),
_products.OrderBy(product => product, comparer), comparer);
}
We used instance of _productService and called the GetAllProducts() method, that will ultimately execute on mocked UnitOfWork and Repository to fetch test data from _products list. The products returned from the method are of type BusinessEntities.ProductEntity and we need to compare the returned products with our existing _products list, such as the list of DataModel.Product (a mocked database entity) so we need to convert the returned BusinessEntities.ProductEntity list to DataModel.Product list. We do this with the following line of code:
var productList =
products.Select(
productEntity =>
new Product {ProductId = productEntity.ProductId, ProductName = productEntity.ProductName}).ToList();
Now we got two lists to compare, one _products list i.e. the actual products and another productList i.e. the products returned from the service. I have written a helper class and compare method to convert the two Product list in TestHelper project. This method checks the list items and compares them for equality of values. You can add a class named ProductComparer to TestHelper project with the following implementations:
public class ProductComparer : IComparer, IComparer
{
public int Compare(object expected, object actual)
{
var lhs = expected as Product;
var rhs = actual as Product;
if (lhs == null || rhs == null) throw new InvalidOperationException();
return Compare(lhs, rhs);
}

public int Compare(Product expected, Product actual)
{
int temp;
return (temp = expected.ProductId.CompareTo(actual.ProductId)) != 0 ? temp : expected.ProductName.CompareTo(actual.ProductName);
}
}</product>
To assert the result we use CollectionAssert.AreEqual of NUnit where we pass both the lists and comparer.
CollectionAssert.AreEqual(
productList.OrderBy(product => product, comparer),
_products.OrderBy(product => product, comparer), comparer);
Since I have the NUnit plugin in my Visual Studio provided by ReSharper, let me debug the test method to see the actual result of Assert. We’ll run all the tests with NUnit UI at the end of the article.
productList:
_products:
We got both the lists and we need to check the comparison of the lists, so I just pressed F5 and got the result on TestUI as:
This shows our test is passed, i.e. the expected and returned result is same.

2. GetAllProductsTestForNull ()

You can also write the test for null check for the same method where you nullify the _products list before you invoke the service method. We actually need to write tests that cover all the exit points of the invoked method.
The following test covers another exit point of the method that returns null in case of no products found.
/// <summary>
/// Service should return null
/// </summary>
[Test]
public void GetAllProductsTestForNull()
{
    _products.Clear();
    var products = _productService.GetAllProducts();
    Assert.Null(products);
    SetUpProducts();
}
In the above mentioned test, we first clear the _products list and invoke the service method. Now assert the result for null because our expected result and actual result should be null. I called the SetUpProducts()method again to populate the _products list, but you can do this in the test setup method as well i.e.ReInitializeTest().
Now let’s move to other tests.

3. GetProductByRightIdTest ()

Here we test the GetProductById() method of ProductService. The ideal behavior is that if I invoke the method with a valid id, the method should return the valid product. Now let’s suppose I know the product id for my product named “Mobile” and I invoke the test using that id, so ideally I should get a product with the product name mobile.
/// <summary>
 /// Service should return product if correct id is supplied
 /// </summary>
 [Test]
 public void GetProductByRightIdTest()
 {
     var mobileProduct = _productService.GetProductById(2);
     if (mobileProduct != null)
     {
         Mapper.CreateMap();
         var productModel = Mapper.Map(mobileProduct);
         AssertObjects.PropertyValuesAreEquals(productModel,
                                               _products.Find(a => a.ProductName.Contains("Mobile")));
     }
 }
The above code is self-explanatory except the line AssertObjects.PropertyValuesAreEquals.
_productService.GetProductById(2); line fetches the product with product id 2.
Mapper.CreateMap();
var productModel = Mapper.Map(mobileProduct);
The above code maps the returned custom ProductEntity to DataModel.Product
AssertObjects is one more class I have added inside the TestHelper class. The purpose of this class is to compare the properties of two objects. This is a common generic class applicable for all type of class objects having properties. Its method PropertyValuesAreEquals() checks for equality of the properties.

AssertObjects class

using System.Collections;
using System.Reflection;
using NUnit.Framework;

namespace TestsHelper
{
    public static class AssertObjects
    {
        public static void PropertyValuesAreEquals(object actual, object expected)
        {
            PropertyInfo[] properties = expected.GetType().GetProperties();
            foreach (PropertyInfo property in properties)
            {
                object expectedValue = property.GetValue(expected, null);
                object actualValue = property.GetValue(actual, null);

                if (actualValue is IList)
                AssertListsAreEquals(property, (IList)actualValue, (IList)expectedValue);
                else if (!Equals(expectedValue, actualValue))
                if (property.DeclaringType != null)
                Assert.Fail("Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue);
            }
        }

        private static void AssertListsAreEquals(PropertyInfo property, IList actualList, IList expectedList)
        {
        if (actualList.Count != expectedList.Count)
            Assert.Fail("Property {0}.{1} does not match. Expected IList containing {2} elements but was IList containing {3} elements", 
            property.PropertyType.Name,
            property.Name, expectedList.Count, actualList.Count);

            for (int i = 0; i < actualList.Count; i++)
            if (!Equals(actualList[i], expectedList[i]))
            Assert.Fail("Property {0}.{1} does not match. Expected IList with element {1} equals to {2} but was IList with element {1} equals to {3}", property.PropertyType.Name, property.Name, expectedList[i], actualList[i]);
        }
    }
}
Running the test,

4. GetProductByWrongIdTest ()

In this test we test the service method with wrong id and expect null in return.
/// <summary>
/// Service should return null
/// </summary>
[Test]
public void GetProductByWrongIdTest()
{
    var product = _productService.GetProductById(0);
    Assert.Null(product);
}

5. AddNewProductTest ()

In this unit test we test the CreateProduct() method of ProductService. Following is the unit test written for creating a new product.
/// <summary>
/// Add new product test
/// </summary>
[Test]
public void AddNewProductTest()
{
    var newProduct = new ProductEntity()
    {
    ProductName = "Android Phone"
    };

    var maxProductIDBeforeAdd = _products.Max(a => a.ProductId);
    newProduct.ProductId = maxProductIDBeforeAdd + 1;
    _productService.CreateProduct(newProduct);
    var addedproduct = new Product() {ProductName = newProduct.ProductName, ProductId = newProduct.ProductId};
    AssertObjects.PropertyValuesAreEquals(addedproduct, _products.Last());
    Assert.That(maxProductIDBeforeAdd + 1, Is.EqualTo(_products.Last().ProductId));
}
In the above code I have created a dummy product with product name “Android Phone” and assigned the product id as the incremented id to the maximum value of productId of the product that lies in _products list. Ideally if my test is success, the added product should reflect in _products list as last product with maximum product id. To verify the result, I have used two asserts. The first one checks the properties of expected and actual product and second one verifies the product id.
var addedproduct = new Product() {ProductName = newProduct.ProductName, ProductId = newProduct.ProductId};
addedProduct is the custom product that is expected to be added in the _products list and_products.Last() gives us last product of the list. So,
AssertObjects.PropertyValuesAreEquals(addedproduct, _products.Last()); checks for all the properties of dummy as well as last added product and,
Assert.That(maxProductIDBeforeAdd + 1, Is.EqualTo(_products.Last().ProductId)); checks if the last product added has the same product id as supplied while creating the product.
After full execution,
The test passes, that means the expected value that was product id 6 was equal to the product id of the last added product in _products list. And we can also see that, earlier we had only five products in _products list and now we have added a 6th one.

6. UpdateProductTest ()

This is the unit test to check if the product is updated or not. This test is for UpdateProduct() method ofProductService.
/// <summary>
/// Update product test
/// </summary>
[Test]
public void UpdateProductTest()
{
    var firstProduct = _products.First();
    firstProduct.ProductName = "Laptop updated";
    var updatedProduct = new ProductEntity()
    {ProductName = firstProduct.ProductName, ProductId = firstProduct.ProductId};
    _productService.UpdateProduct(firstProduct.ProductId, updatedProduct);
    Assert.That(firstProduct.ProductId, Is.EqualTo(1)); // hasn't changed
    Assert.That(firstProduct.ProductName, Is.EqualTo("Laptop updated")); // Product name changed

}
In this test I am trying to update first product from _products list. I have changed the product name to “Laptop Updated” and invoked the UpdateProduct () method of ProductService. I have made two asserts to check the updated product from _products list, one for productId and second for product name. We see that we get the updated product while we assert.

7. DeleteProductTest ()

The following is the test for the DeleteProduct () method in ProductService.
/// <summary>
/// Delete product test
/// </summary>
[Test]
public void DeleteProductTest()
{
    int maxID = _products.Max(a => a.ProductId); // Before removal
    var lastProduct = _products.Last();

    // Remove last Product
    _productService.DeleteProduct(lastProduct.ProductId);
    Assert.That(maxID, Is.GreaterThan(_products.Max(a => a.ProductId)));   // Max id reduced by 1
}
I have written the test to verify the max id of product from the list of products. Get max id of the product, delete the last product and check the max id of the product from the list. The prior max id should be greater than the last product’s product id.
Max id before delete was 5 and after delete is 4 that means a product is deleted from _products list therefore statement : Assert.That(maxID, Is.GreaterThan(_products.Max(a => a.ProductId))); passes as 5 is greater than 4.
We have covered all the methods of ProductService under unit tests. The following is the final class that covers all the tests for this service.
#region using namespaces.
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using BusinessEntities;
using DataModel;
using DataModel.GenericRepository;
using DataModel.UnitOfWork;
using Moq;
using NUnit.Framework;
using TestsHelper;

#endregion

namespace BusinessServices.Tests
{
    /// <summary>
    /// Product Service Test
    /// </summary>
    public class ProductServicesTest
    {
        #region Variables

        private IProductServices _productService;
        private IUnitOfWork _unitOfWork;
        private List _products;
        private GenericRepository _productRepository;
        private WebApiDbEntities _dbEntities;
        #endregion

        #region Test fixture setup

        /// <summary>
        /// Initial setup for tests
        /// </summary>
        [TestFixtureSetUp]
        public void Setup()
        {
            _products = SetUpProducts();
        }

        #endregion

        #region Setup

        /// <summary>
        /// Re-initializes test.
        /// </summary>
        [SetUp]
        public void ReInitializeTest()
        {
            _dbEntities = new Mock().Object;
            _productRepository = SetUpProductRepository();
            var unitOfWork = new Mock();
            unitOfWork.SetupGet(s => s.ProductRepository).Returns(_productRepository);
            _unitOfWork = unitOfWork.Object;
            _productService = new ProductServices(_unitOfWork);
        }

        #endregion

        #region Private member methods

        /// <summary>
        /// Setup dummy repository
        /// </summary>
        /// <returns></returns>
        private GenericRepository SetUpProductRepository()
        {
            // Initialise repository
            var mockRepo = new Mock<GenericRepository>(MockBehavior.Default, _dbEntities);

            // Setup mocking behavior
            mockRepo.Setup(p => p.GetAll()).Returns(_products);

            mockRepo.Setup(p => p.GetByID(It.IsAny()))
            .Returns(new Func(
            id => _products.Find(p => p.ProductId.Equals(id))));

            mockRepo.Setup(p => p.Insert((It.IsAny())))
            .Callback(new Action(newProduct =>
            {
                dynamic maxProductID = _products.Last().ProductId;
                dynamic nextProductID = maxProductID + 1;
                newProduct.ProductId = nextProductID;
                _products.Add(newProduct);
            }));

            mockRepo.Setup(p => p.Update(It.IsAny()))
            .Callback(new Action(prod =>
            {
                var oldProduct = _products.Find(a => a.ProductId == prod.ProductId);
                oldProduct = prod;
            }));

            mockRepo.Setup(p => p.Delete(It.IsAny()))
            .Callback(new Action(prod =>
            {
                var productToRemove =
                _products.Find(a => a.ProductId == prod.ProductId);

                if (productToRemove != null)
                    _products.Remove(productToRemove);
            }));

            // Return mock implementation object
            return mockRepo.Object;
        }

        /// <summary>
        /// Setup dummy products data
        /// </summary>
        /// <returns></returns>
        private static List SetUpProducts()
        {
            var prodId = new int();
            var products = DataInitializer.GetAllProducts();
            foreach (Product prod in products)
                prod.ProductId = ++prodId;
            return products;

        }

        #endregion

        #region Unit Tests

        /// <summary>
        /// Service should return all the products
        /// </summary>
        [Test]
        public void GetAllProductsTest()
        {
            var products = _productService.GetAllProducts();
            if (products != null)
            {
                var productList =
                products.Select(
                productEntity =>
                new Product { ProductId = productEntity.ProductId, ProductName = productEntity.ProductName }).
                ToList();
                var comparer = new ProductComparer();
                CollectionAssert.AreEqual(
                productList.OrderBy(product => product, comparer),
                _products.OrderBy(product => product, comparer), comparer);
            }
        }

        /// <summary>
        /// Service should return null
        /// </summary>
        [Test]
        public void GetAllProductsTestForNull()
        {
            _products.Clear();
            var products = _productService.GetAllProducts();
            Assert.Null(products);
            SetUpProducts();
        }

        /// <summary>
        /// Service should return product if correct id is supplied
        /// </summary>
        [Test]
        public void GetProductByRightIdTest()
        {
            var mobileProduct = _productService.GetProductById(2);
            if (mobileProduct != null)
            {
                Mapper.CreateMap();
                var productModel = Mapper.Map(mobileProduct);
                AssertObjects.PropertyValuesAreEquals(productModel,
                _products.Find(a => a.ProductName.Contains("Mobile")));
            }
        }

        /// <summary>
        /// Service should return null
        /// </summary>
        [Test]
        public void GetProductByWrongIdTest()
        {
            var product = _productService.GetProductById(0);
            Assert.Null(product);
        }

        /// <summary>
        /// Add new product test
        /// </summary>
        [Test]
        public void AddNewProductTest()
        {
            var newProduct = new ProductEntity()
            {
                ProductName = "Android Phone"
            };

            var maxProductIDBeforeAdd = _products.Max(a => a.ProductId);
            newProduct.ProductId = maxProductIDBeforeAdd + 1;
            _productService.CreateProduct(newProduct);
            var addedproduct = new Product() { ProductName = newProduct.ProductName, ProductId = newProduct.ProductId };
            AssertObjects.PropertyValuesAreEquals(addedproduct, _products.Last());
            Assert.That(maxProductIDBeforeAdd + 1, Is.EqualTo(_products.Last().ProductId));
        }

        /// <summary>
        /// Update product test
        /// </summary>
        [Test]
        public void UpdateProductTest()
        {
            var firstProduct = _products.First();
            firstProduct.ProductName = "Laptop updated";
            var updatedProduct = new ProductEntity() { ProductName = firstProduct.ProductName, ProductId = firstProduct.ProductId };
            _productService.UpdateProduct(firstProduct.ProductId, updatedProduct);
            Assert.That(firstProduct.ProductId, Is.EqualTo(1)); // hasn't changed
            Assert.That(firstProduct.ProductName, Is.EqualTo("Laptop updated")); // Product name changed
        }

        /// <summary>
        /// Delete product test
        /// </summary>
        [Test]
        public void DeleteProductTest()
        {
            int maxID = _products.Max(a => a.ProductId); // Before removal
            var lastProduct = _products.Last();

            // Remove last Product
            _productService.DeleteProduct(lastProduct.ProductId);
            Assert.That(maxID, Is.GreaterThan(_products.Max(a => a.ProductId))); // Max id reduced by 1
        }

        #endregion


        #region Tear Down

        /// <summary>
        /// Tears down each test data
        /// </summary>
        [TearDown]
        public void DisposeTest()
        {
            _productService = null;
            _unitOfWork = null;
            _productRepository = null;
            if (_dbEntities != null)
                _dbEntities.Dispose();
        }

        #endregion

        #region TestFixture TearDown.

        /// <summary>
        /// TestFixture teardown
        /// </summary>
        [TestFixtureTearDown]
        public void DisposeAllObjects()
        {
            _products = null;
        }

        #endregion
    }
}

TokenService Tests

Now that we have completed all the tests for ProductService, I am sure you must have got an idea on how to write unit tests for methods. Note that primarily unit tests are only written to publically exposed methods because the private methods automatically get tested through those public methods in the class. I’ll not explain too much theory for TokenService tests and only navigate through code. I’ll explain the details wherever necessary.

Tests Setup

Add a new class named TokenServicesTests.cs in BusinessServices.Tests project.
Declare variables
Define the private variable that we’ll use in the class to write tests,
#region Variables
private ITokenServices _tokenServices;
private IUnitOfWork _unitOfWork;
private List _tokens;
private GenericRepository _tokenRepository;
private WebApiDbEntities _dbEntities;
private const string SampleAuthToken = "9f907bdf-f6de-425d-be5b-b4852eb77761";
#endregion
Here _tokenService will hold mock for TokenServices_unitOfWork for UnitOfWork class, __tokens will hold dummy tokens from DataInitializer class of TestHelper project, _tokenRepository and_dbEntities holds mock for Token Repository and WebAPIDbEntities from DataModel project respectively
Write Test Fixture Setup
#region Test fixture setup

/// <summary>
/// Initial setup for tests
/// </summary>
[TestFixtureSetUp]
public void Setup()
{
    _tokens = SetUpTokens();
}

#endregion
SetUpTokens () method fetches tokens from DataInitializer class and not from database and assigns a unique id to each token by iterating on them.
/// <summary>
/// Setup dummy tokens data
/// </summary>
/// <returns></returns>
private static List SetUpTokens()
{
    var tokId = new int();
    var tokens = DataInitializer.GetAllTokens();
    foreach (Token tok in tokens)
        tok.TokenId = ++tokId;
    return tokens;
}
The result data is assigned to __tokens list to be used in setting up mock repository and in every individual test for comparison of actual vs resultant output.
Write Test Fixture Tear Down
#region TestFixture TearDown.

/// <summary>
/// TestFixture teardown
/// </summary>
[TestFixtureTearDown]
public void DisposeAllObjects()
{
    _tokens = null;
}

#endregion
Write Test Setup
#region Setup

    /// <summary>
    /// Re-initializes test.
    /// </summary>
    [SetUp]
    public void ReInitializeTest()
    {
        _dbEntities = new Mock().Object;
        _tokenRepository = SetUpTokenRepository();
        var unitOfWork = new Mock();
        unitOfWork.SetupGet(s => s.TokenRepository).Returns(_tokenRepository);
        _unitOfWork = unitOfWork.Object;
        _tokenServices = new TokenServices(_unitOfWork);
    }

#endregion
Write Test Tear down
#region Tear Down

/// <summary>
/// Tears down each test data
/// </summary>
[TearDown]
public void DisposeTest()
{
    _tokenServices = null;
    _unitOfWork = null;
    _tokenRepository = null;
    if (_dbEntities != null)
        _dbEntities.Dispose();
}

#endregion
Mocking Repository
private GenericRepository SetUpTokenRepository()
{
// Initialise repository
var mockRepo = new Mock<GenericRepository>(MockBehavior.Default, _dbEntities);

// Setup mocking behavior
mockRepo.Setup(p => p.GetAll()).Returns(_tokens);

mockRepo.Setup(p => p.GetByID(It.IsAny()))
.Returns(new Func(
id => _tokens.Find(p => p.TokenId.Equals(id))));

mockRepo.Setup(p => p.GetByID(It.IsAny()))
.Returns(new Func(
authToken => _tokens.Find(p => p.AuthToken.Equals(authToken))));

mockRepo.Setup(p => p.Insert((It.IsAny())))
.Callback(new Action(newToken =>
{
dynamic maxTokenID = _tokens.Last().TokenId;
dynamic nextTokenID = maxTokenID + 1;
newToken.TokenId = nextTokenID;
_tokens.Add(newToken);
}));

mockRepo.Setup(p => p.Update(It.IsAny()))
.Callback(new Action(token =>
{
var oldToken = _tokens.Find(a => a.TokenId == token.TokenId);
oldToken = token;
}));

mockRepo.Setup(p => p.Delete(It.IsAny()))
.Callback(new Action(prod =>
{
var tokenToRemove =
_tokens.Find(a => a.TokenId == prod.TokenId);

if (tokenToRemove != null)
_tokens.Remove(tokenToRemove);
}));
//Create setup for other methods too. note non virtauls methods can not be set up

// Return mock implementation object
return mockRepo.Object;
}
Note, while mocking repository, I have setup two mocks for GetById(). There is a minor change I did in the database, I have marked AuthToken field as a primary key too. So it may be a situation where mock gets confused on calling the method that for which primary key the request has been made. So I have implemented the mock both for TokenId and AuthToken field:
mockRepo.Setup(p => p.GetByID(It.IsAny())).Returns(new Func(
id => _tokens.Find(p => p.TokenId.Equals(id))));

mockRepo.Setup(p => p.GetByID(It.IsAny())).Returns(new Func(
authToken => _tokens.Find(p => p.AuthToken.Equals(authToken))));
The overall setup is of same nature as we wrote for ProductService. Let us move on to unit tests.

1. GenerateTokenByUseridTest ()

This unit test is to test the GenerateToken method of TokenServices business service. In this method, a new token is generated in the database against a user. We’ll use _tokens list for all these transactions. Currently we have only two token entries in _tokens list generated from DataInitializer. Now when the test executes it should expect one more token to be added to the list.
[Test]
 public void GenerateTokenByUserIdTest()
 {
     const int userId = 1;
     var maxTokenIdBeforeAdd = _tokens.Max(a => a.TokenId);
     var tokenEntity = _tokenServices.GenerateToken(userId);
     var newTokenDataModel = new Token()
                                 {
                                     AuthToken = tokenEntity.AuthToken,
                                     TokenId = maxTokenIdBeforeAdd+1,
                                     ExpiresOn = tokenEntity.ExpiresOn,
                                     IssuedOn = tokenEntity.IssuedOn,
                                     UserId = tokenEntity.UserId
                                 };
     AssertObjects.PropertyValuesAreEquals(newTokenDataModel, _tokens.Last());
 }
I have taken a default user id as 1, and stored the max token id from the list of tokens. Call the service methodGenerateTokenEntity (). Since our service method returns BusinessEntities.TokenEntity, we need to map it to new DataModel.Token object for comparison. So the expected result is that all the properties of this token should match the last token of the _token list assuming that list is updated through the test.
Now since all the properties of the resultant and actual object match, so our test passes.

2. ValidateTokenWithRightAuthToken ()

/// <summary>
/// Validate token test
/// </summary>
[Test]
public void ValidateTokenWithRightAuthToken()
{
    var authToken = Convert.ToString(SampleAuthToken);
    var validationResult = _tokenServices.ValidateToken(authToken);
    Assert.That(validationResult,Is.EqualTo(true));
}
This test validates AuthToken through ValidateToken method of TokenService. Ideally if correct token is passed, the service should return true.
Here we get validationResult as true therefore test should pass.

3. ValidateTokenWithWrongAuthToken ()

Testing the same method for its alternate exit point, therefore, with the wrong token, the service should return false.
[Test]
 public void ValidateTokenWithWrongAuthToken()
 {
     var authToken = Convert.ToString("xyz");
     var validationResult = _tokenServices.ValidateToken(authToken);
     Assert.That(validationResult, Is.EqualTo(false));
 }
Here validationResult is false, and is compared to false value, so test should ideally pass.

UserService Tests

I have tried writing unit tests for UserService as per our service implementations, but encountered an error while mocking up our repositories Get () method that takes predicate or where condition as a parameter.
public TEntity Get(Func where)
     {
         return DbSet.Where(where).FirstOrDefault();
     }
Our service methods heavily depend on the Get method so none of the methods could be tested, but apart from this you can search for any other mocking framework that takes care of these situations. I guess this is a bug in the mocking framework. Alternatively, refrain from using Get method with predicate (I would not suggest this approach as it is against the testing strategy. Our tests should not be limited to technical feasibility of methods). I got the following error while mocking repository:
“Invalid setup on a non-virtual (overridable in VB)”. I have commented out all UserService Unit test code, you can find it in available source code.

Test through NUnit UI

We have completed almost all the BusinessServices test, now let us try to execute these test on NUnit UI.
  1. Step 1:Launch NUnit UI. I have already explained how to install NUnit on the windows machine. Just launch the NUnit interface with its launch icon
  2. Step 2 :Once the interface opens, click on File -> New Project and name the project as WebAPI.nunit and save it at any windows location.


  3. Step 3:Now, click on Project-> Add Assembly and browse for BusinessServices.Tests.dll (The library created for your unit test project when compiled)

  4. Step 4:Once the assembly is browsed, you’ll see all the unit tests for that test project gets loaded in the UI and are visible on the interface.
  5. Step 5:At the right hand side panel of the interface, you’ll see a Run button that runs all the tests of business service. Just select the node BusinessServices in the tests tree on left side and press Run button on the right side.

    Once you run the tests, you’ll get green progress bar on right side and tick mark on all the tests on left side. That means all the tests are passed. In case any test fails, you’ll get cross mark on the test and red progress bar on right side.

    But here, all of our tests are passed.

WebAPI Tests

Unit tests for WebAPI are not exactly like service methods, but vary in terms of testing HttpResponse, returned JSON, exception responses etc. Note that we’ll mock the classes and repository in a similar way in WebAPI unit tests as we did for services. One way of testing a web api is through web client and testing the actual endpoint or hosted URL of the service, but that is not considered as a unit test, that is called integration testing. In the next part of the article I’ll explain step by step procedure to unit test a web API. We’ll write tests for Product Controller.

Conclusion

In this article we learnt how to write unit tests for core business logic and primarily on basic CRUD operations. The purpose was to get a basic idea on how unit tests are written and executed. You can add your own flavor to this that helps you in your real time project. My next article which explains unit tests for WebAPI controllers will be the continuation of this part. I hope this was useful to you. You can download the complete source code of this article with packages from GitHub. Happy coding Smile | :)

 

 

RESTful Day #6: Request logging and Exception handling/logging in Web APIs using Action Filters, Exception Filters and NLog


Download Source Code from GitHub

Introduction

We have been learning a lot about WebAPI, its uses, implementations, and security aspects since last five articles of the series. This article of the series will explain how we can handle requests and log them for tracking and for the sake of debugging, how we can handle exceptions and log them. We’ll follow a centralized way of handling exceptions in WebAPI and write our custom classes to be mapped to the type of exception that we encounter and log the accordingly. I’ll use NLog to log requests and exceptions as well. We’ll leverage the capabilities of Exception Filters and Action Filters to centralize request logging and exception handling in WebAPI.

Roadmap

The following is the roadmap I have setup to learn WebAPI step by step,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Request Logging

Since we are writing web services, we are exposing our end points. We must know where the requests are coming from and what requests are coming to our server. Logging could be very beneficial and helps us in a lot of ways like, debugging, tracing, monitoring and analytics.

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below or one can also implement this approach in their existing solution as well.

Setup NLog in WebAPI

NLog serves various purposes but primarily logging. We’ll use NLog for logging into files and windows event as well. You can read more about NLog at http://NLog-project.org/
One can use the sample application that we used in Day#5 or can have any other application as well. I am using the existing sample application that we were following throughout all the parts of this series. Our application structure looks something like:

Step 1: Download NLog Package

Right click WebAPI project and select manage Nuget Packages from the list. When the Nuget Package Manager appears, search for NLog. You’ll get Nlog like shown in image below, just install it to our project.

After adding this you will find following NLog dll referenced in your application.

Step 2: Configuring NLog

To configure NLog with application add following settings in our existing WebAPI web.config file,

ConfigSection –

Configuration Section – I have added the section to configuration and defined the path and format dynamic target log file name, also added the eventlog source to Api Services.

As mentioned in above target path, I have also created to “APILog” folder in the base directory of application.

Now we have configured the NLog in our application, and it is ready to start work for request logging. Note that in the rules section we have defined rules for logging in files as well as in windows events log as well, you can choose both of them or can opt for one too. Let’s start with logging request in application, with action filters –

NLogger Class

Add a folder “Helpers” in the API, which will segregate the application code for readability, better understanding and maintainability.

To start add our main class “NLogger“, which will responsible for all types of errors and info logging, to same Helper folder. Here NLogger class implements ITraceWriter interface, which provides “Trace” method for the service request.
#region Using namespaces.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Tracing;
using NLog;
using System.Net.Http;
using System.Text;
using WebApi.ErrorHelper;
#endregion

namespace WebApi.Helpers
{
    /// <summary>
    /// Public class to log Error/info messages to the access log file
    /// </summary>
    public sealed class NLogger : ITraceWriter
    {
        #region Private member variables.
        private static readonly Logger ClassLogger = LogManager.GetCurrentClassLogger();

        private static readonly Lazy<Dictionary<TraceLevel, Action<string>>> LoggingMap = new Lazy<Dictionary<TraceLevel, Action<string>>>(() => new Dictionary<TraceLevel, Action<string>> { { TraceLevel.Info, ClassLogger.Info }, { TraceLevel.Debug, ClassLogger.Debug }, { TraceLevel.Error, ClassLogger.Error }, { TraceLevel.Fatal, ClassLogger.Fatal }, { TraceLevel.Warn, ClassLogger.Warn } });
        #endregion

        #region Private properties.
        /// <summary>
        /// Get property for Logger
        /// </summary>
        private Dictionary<TraceLevel, Action<string>> Logger
        {
            get { return LoggingMap.Value; }
        }
        #endregion

        #region Public member methods.
        /// <summary>
        /// Implementation of TraceWriter to trace the logs.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="category"></param>
        /// <param name="level"></param>
        /// <param name="traceAction"></param>
        public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action traceAction)
        {
            if (level != TraceLevel.Off)
            {
                if (traceAction != null && traceAction.Target != null)
                {
                    category = category + Environment.NewLine + "Action Parameters : " + traceAction.Target.ToJSON();
                }
                var record = new TraceRecord(request, category, level);
                if (traceAction != null) traceAction(record);
                Log(record);
            }
        }
        #endregion

        #region Private member methods.
        /// <summary>
        /// Logs info/Error to Log file
        /// </summary>
        /// <param name="record"></param>
        private void Log(TraceRecord record)
        {
            var message = new StringBuilder();

            if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

            if (record.Request != null)
            {
                if (record.Request.Method != null)
                    message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            
            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }
        #endregion
    }
}

Adding Action Filter

Action filter will be responsible for handling all the incoming requests to our APIs and logging them using NLogger class. We have “OnActionExecuting” method that is implicitly called if we mark our controllers or global application to use that particular filter. So each time any action of any controller will be hit, our “OnActionExecuting” method will execute to log the request.

Step 1: Adding LoggingFilterAttribute class

Create a class LoggingFilterAttribute to “ActionFilters” folder and add following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Filters;
using System.Web.Http.Controllers;
using System.Web.Http.Tracing;
using System.Web.Http;
using WebApi.Helpers;


namespace WebApi.ActionFilters
{
    public class LoggingFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Info(filterContext.Request, "Controller : " + filterContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + filterContext.ActionDescriptor.ActionName, "JSON", filterContext.ActionArguments);
        }
    }
}
The LoggingFilterAttribute class derived from ActionFilterAttribute, which is underSystem.Web.Http.Filters and overriding the OnActionExecuting method.
Here I have replaced the default “ITraceWriter” service with our NLogger class instance in the controller’s service container. Now GetTraceWriter() method will return our instance (instance NLogger class) and Info() will call trace() method of our NLogger class.
Note that the code below.
GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
is used to resolve dependency between ITaceWriter and NLogger class. Thereafter we use a variable namedtrace to get the instance and trace.Info() is used to log the request and whatever text we want to add along with that request.

Step 2: Registering Action Filter (LoggingFilterAttribute)

In order to register the created action filter to application’s filters, just add a new instance of your action filter toconfig.Filters in WebApiConfig class.
using System.Web.Http;
using WebApi.ActionFilters;

namespace WebApi.App_Start
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new LoggingFilterAttribute());
        }
    }
}
Now this action filter is applicable to all the controllers and actions in our project. You may not believe but request logging is done. It’s time to run the application and validate our homework.

Running the application

Let’s run the application and try to make a call, using token based authorization, we have already covered authorization in day#5. You first need to authenticate your request using login service and then that service will return a token for making calls to other services. Use that token to make calls to other services. For more details you can read day 5 of this series.
Just run the application, we get
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and typing WebAPITestClient in searchbox in online packages
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below:
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
GET:
POST:
PUT:
DELETE:
You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service:
Service for Get All products:
In the below case, I have already generated the token and now I am using it to make call to fetch all the products from the products table in the database.

Here I have called allproducts API, Add the value for parameter Id and “Token” header with its current value and click to get the result:

Now let’s see what happens to our APILog folder in application. Here you find the API log has been created, with the same name we have configured in NLog configuration in web.config file. The log file contains all the supplied details like Timestamp, Method type, URL , Header information (Token), Controller name, action and action parameters. You can also add more details to this log which you deem important for your application.

Logging Done!

Exception Logging

Our logging setup is completed, now we’ll focus on centralizing exception logging as well, so that none of the exception escapes without logging itself. Logging exception is of very high importance, it keeps track of all the exceptions. No matter business or application or system exceptions, all of them have to be logged.

Implementing Exception logging

Step 1: Exception Filter Attribute

Now we will add an action filter in our application for logging the exceptions. For this create a class,GlobalExceptionAttribute to “ActionFilter” folder and add the code below, the class is derived fromExceptionFilterAttribute, which is under System.Web.Http.Filters.
I override the OnException() method and replace the default “ITraceWriter” service with our NLogger class instance in the controller’s service container, same as we have done in Action logging in above section. Now theGetTraceWriter() method will return our instance (instance NLogger class) and Info() will call trace()method of NLogger class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Filters;
using System.Web.Http;
using System.Web.Http.Tracing;
using WebApi.Helpers;
using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using System.Net;

namespace WebApi.ActionFilters
{
    /// <summary>
    /// Action filter to handle for Global application errors.
    /// </summary>
    public class GlobalExceptionAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Error(context.Request, "Controller : " + context.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + context.ActionContext.ActionDescriptor.ActionName, context.Exception);

            var exceptionType = context.Exception.GetType();

            if (exceptionType == typeof(ValidationException))
            {
                var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(context.Exception.Message), ReasonPhrase = "ValidationException", };
                throw new HttpResponseException(resp);

            }
            else if (exceptionType == typeof(UnauthorizedAccessException))
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.Unauthorized));
            }
            else
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.InternalServerError));
            }
        }
    }
}

Step 2: Modify NLogger Class

Our NLogger class is capable to log all info and events, I have done some changes in private method Log() to handle the exceptions
#region Private member methods.
/// <summary>
/// Logs info/Error to Log file
/// </summary>
/// <param name="record"></param>
private void Log(TraceRecord record)
{
var message = new StringBuilder();

if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

      if (record.Request != null)
{
       if (record.Request.Method != null)
            message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            if (record.Exception != null && !string.IsNullOrWhiteSpace(record.Exception.GetBaseException().Message))
            {
                var exceptionType = record.Exception.GetType();
                message.Append(Environment.NewLine);
                message.Append("").Append("Error: " + record.Exception.GetBaseException().Message + Environment.NewLine);
            }

            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }

Step 3: Modify Controller for Exception

Our application is now ready to run, but there is no exception in our code, so I added a throw exception code inProductController, just the Get(int id) method so that it can throw exception for testing our exception logging mechanism. It will throw an exception if the product is not there in database with the provided id.
  // GET api/product/5
 [GET("productid/{id?}")]
 [GET("particularproduct/{id?}")]
 [GET("myproduct/{id:range(1, 3)}")]
 public HttpResponseMessage Get(int id)
 {
var product = _productServices.GetProductById(id);
      if (product != null)
       return Request.CreateResponse(HttpStatusCode.OK, product);

 throw new Exception("No product found for this id");
      //return Request.CreateErrorResponse(HttpStatusCode.NotFound,   "No product found for this id");
 }

Step 4: Run the application

Run the application and click on Product/all API
Add the parameter id value to 1 and header Token with it’s current value, click on send button to get the result:
Now we can see that the Status is 200/OK, and we also get a product with the provided id in the response body. Let’s see the API log now:
The log has captured the call of Product API, now provide a new product id as parameter, which is not there in database, I am using 12345 as product id and result is:

We can see there is an 500/Internal Server Error now in response status, let’s check the API Log:

Well, now the log has captured both the event and error of same call on the server, you can see call log details and the error with provided error message in the log.

Custom Exception logging

In the above section we have implemented exception logging, but there is default system response and status (i.e. 500/Internal Server Error). It will be always good to have your own custom response and exceptions for your API. That will be easier for client to consume and understand the API responses.

Step 1: Add Custom Exception Classes

Add “Error Helper” folder to application to maintain our custom exception classes separately and add “IApiExceptions” interface to newly created “ErrorHelper” folder –
Add following code the IApiExceptions interface, this will serve as a template for all exception classes, I have added four common properties for our custom classes to maintain Error Code, ErrorDescription, HttpStatus (Contains the values of status codes defined for HTTP) and ReasonPhrase.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// IApiExceptions Interface
    /// </summary>
    public interface IApiExceptions
    {
        /// <summary>
        /// ErrorCode
        /// </summary>
        int ErrorCode { get; set; }
        /// <summary>
        /// ErrorDescription
        /// </summary>
        string ErrorDescription { get; set; }
        /// <summary>
        /// HttpStatus
        /// </summary>
        HttpStatusCode HttpStatus { get; set; }
        /// <summary>
        /// ReasonPhrase
        /// </summary>
        string ReasonPhrase { get; set; }
    }
}
Here, I divided our exceptions in three categories:
  1. API Exceptions – for API level exceptions.
  2. Business Exceptions – for exceptions at business logic level.
  3. Data Exceptions – Data related exceptions.
To implement this create a three new classes ApiException.cs, ApiDataException.cs and ApiBusinessExceptionclasses to same folder which implements IApiExceptions interface with following code to the classes.
#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization;
#endregion


namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }
        
        string reasonPhrase = "ApiException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }
        #endregion
    }
}
I have initialized ReasonPhrase property with different default values in these classes to differentiate the implementation, you can use implement your custom classes as per your application needs.
The directives applied on class as Serializable and DataContract to make sure that the class defines or implements a data contract is serializable and can be serialize by a serializer.
Note: Add reference of “System.Runtime.Serialization.dll” DLL if you facing any assembly issue.
In the same way add “ApiBusinessException” and “ApiDataException” classes into the same folder, with the following code –
#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization; 
#endregion

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Business Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiBusinessException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }

        string reasonPhrase = "ApiBusinessException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }
        #endregion

        #region Public Constructor.
        /// <summary>
        /// Public constructor for Api Business Exception
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="errorDescription"></param>
        /// <param name="httpStatus"></param>
        public ApiBusinessException(int errorCode, string errorDescription, HttpStatusCode httpStatus)
        {
            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
            HttpStatus = httpStatus;
        } 
        #endregion

    }
}

#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization;
#endregion

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Data Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiDataException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }

        string reasonPhrase = "ApiDataException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }

        #endregion

        #region Public Constructor.
        /// <summary>
        /// Public constructor for Api Data Exception
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="errorDescription"></param>
        /// <param name="httpStatus"></param>
        public ApiDataException(int errorCode, string errorDescription, HttpStatusCode httpStatus)
        {
            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
            HttpStatus = httpStatus;
        }
        #endregion
    }
}

JSon Serializers

There are some objects need to be serialized in JSON, to log and to transfer through the modules, for this I have add some extension methods to Object class.
For that add “System.Web.Extensions.dll” reference to project and add “JSONHelper” class to Helpers folder, with following code:
#region Using namespaces.
using System.Web.Script.Serialization;
using System.Data;
using System.Collections.Generic;
using System;

#endregion

namespace WebApi.Helpers
{
    public static class JSONHelper
    {
         #region Public extension methods.
        /// <summary>
        /// Extened method of object class, Converts an object to a json string.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToJSON(this object obj)
        {
            var serializer = new JavaScriptSerializer();
            try
            {
                return serializer.Serialize(obj);
            }
            catch(Exception ex)
            {
                return "";
            }
        }
         #endregion
    }
}
In the above code “ToJSON()” method is an extension of base Object class, which serializes supplied the object to a JSON string. The method using “JavaScriptSerializer” class which exists in “System.Web.Script.Serialization“.

Modify NLogger Class

For exception handling I have modified the Log() method of NLogger, which will now handle the different API exceptions.
/// <summary>
/// Logs info/Error to Log file
/// </summary>
/// <param name="record"></param>
private void Log(TraceRecord record)
{
var message = new StringBuilder();

      if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

            if (record.Request != null)
            {
                if (record.Request.Method != null)
                    message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            if (record.Exception != null && !string.IsNullOrWhiteSpace(record.Exception.GetBaseException().Message))
            {
                var exceptionType = record.Exception.GetType();
                message.Append(Environment.NewLine);
                if (exceptionType == typeof(ApiException))
                {
                    var exception = record.Exception as ApiException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else if (exceptionType == typeof(ApiBusinessException))
                {
                    var exception = record.Exception as ApiBusinessException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else if (exceptionType == typeof(ApiDataException))
                {
                    var exception = record.Exception as ApiDataException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else
                    message.Append("").Append("Error: " + record.Exception.GetBaseException().Message + Environment.NewLine);
            }

            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }
The code above checks the exception object of TraceRecord and updates the logger as per the exception type.

Modify GlobalExceptionAttribute

As we have created GlobalExceptionAttribute to handle all exceptions and create response in case of any exception. Now I have added some new code to this in order to enable the GlobalExceptionAttribute class to handle custom exceptions. I am adding only modified method here for your reference .
public override void OnException(HttpActionExecutedContext context)
{
         GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Error(context.Request, "Controller : " + context.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + context.ActionContext.ActionDescriptor.ActionName, context.Exception);

            var exceptionType = context.Exception.GetType();

            if (exceptionType == typeof(ValidationException))
            {
                var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(context.Exception.Message), ReasonPhrase = "ValidationException", };
                throw new HttpResponseException(resp);

            }
            else if (exceptionType == typeof(UnauthorizedAccessException))
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.Unauthorized, new ServiceStatus() { StatusCode = (int)HttpStatusCode.Unauthorized, StatusMessage = "UnAuthorized", ReasonPhrase = "UnAuthorized Access" }));
            }
            else if (exceptionType == typeof(ApiException))
            {
                var webapiException = context.Exception as ApiException;
                if (webapiException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(webapiException.HttpStatus, new ServiceStatus() { StatusCode = webapiException.ErrorCode, StatusMessage = webapiException.ErrorDescription, ReasonPhrase = webapiException.ReasonPhrase }));
            }
            else if (exceptionType == typeof(ApiBusinessException))
            {
                var businessException = context.Exception as ApiBusinessException;
                if (businessException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(businessException.HttpStatus, new ServiceStatus() { StatusCode = businessException.ErrorCode, StatusMessage = businessException.ErrorDescription, ReasonPhrase = businessException.ReasonPhrase }));
            }
            else if (exceptionType == typeof(ApiDataException))
            {
                var dataException = context.Exception as ApiDataException;
                if (dataException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(dataException.HttpStatus, new ServiceStatus() { StatusCode = dataException.ErrorCode, StatusMessage = dataException.ErrorDescription, ReasonPhrase = dataException.ReasonPhrase }));
            }
            else
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.InternalServerError));
            }
        }
In the above code I have modified the overrided method OnExeption() and created new Http response exception based on the different exception types.

Modify Product Controller

Now modify the Product controller to throw our custom exception form, please look into the Get method I have modified to throw the APIDataException in case if data is not found and APIException in any other kind of error.
// GET api/product/5
[GET("productid/{id?}")]
[GET("particularproduct/{id?}")]
[GET("myproduct/{id:range(1, 3)}")]
public HttpResponseMessage Get(int id)
{
if (id != null)
      {
       var product = _productServices.GetProductById(id);
            if (product != null)
             return Request.CreateResponse(HttpStatusCode.OK, product);

throw new ApiDataException(1001, "No product found for this id.", HttpStatusCode.NotFound);
      }
      throw new ApiException() { ErrorCode = (int)HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..." };
}

Run the application

Run the application and click on Product/all API:
Add the parameter id value to 1 and header Token with its current value, click on send button to get the result:
Now we can see that the Status is 200/OK, and we also get a product with the provided id in the response body. Lets see the API log now –
The log has captured the call of Product API, now provide a new product id as parameter, which is not there in database, I am using 12345 as product id and result is:
We can see, now there is a custom error status code “1001” and messages “No product found for this id.” And the generic status code “500/Internal Server Error” is now replaced with our supplied code “404/ Not Found”, which is more meaningful for the client or consumer.
Lets see the APILog now:
Well, now the log has captured both the event and error of same call on the server, you can see call log details and the error with provided error message in the log with our custom error code, I have only captured error description and error code, but you can add more details in the log as per your application needs.

Update the controller for new Exception Handling

Following is the code for controllers with implementation of custom exception handling and logging:

Product Controller

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AttributeRouting;
using AttributeRouting.Web.Http;
using BusinessEntities;
using BusinessServices;
using WebApi.ActionFilters;
using WebApi.Filters;
using System;
using WebApi.ErrorHelper;

namespace WebApi.Controllers
{
    [AuthorizationRequired]
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {
        #region Private variable.

        private readonly IProductServices _productServices;

        #endregion

        #region Public Constructor

        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController(IProductServices productServices)
        {
            _productServices = productServices;
        }

        #endregion

        // GET api/product
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            throw new ApiDataException(1000, "Products not found", HttpStatusCode.NotFound);
        }

        // GET api/product/5
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            if (id != null)
            {
                var product = _productServices.GetProductById(id);
                if (product != null)
                    return Request.CreateResponse(HttpStatusCode.OK, product);

                throw new ApiDataException(1001, "No product found for this id.", HttpStatusCode.NotFound);
            }
            throw new ApiException() { ErrorCode = (int)HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..." };
        }

        // POST api/product
        [POST("Create")]
        [POST("Register")]
        public int Post([FromBody] ProductEntity productEntity)
        {
            return _productServices.CreateProduct(productEntity);
        }

        // PUT api/product/5
        [PUT("Update/productid/{id}")]
        [PUT("Modify/productid/{id}")]
        public bool Put(int id, [FromBody] ProductEntity productEntity)
        {
            if (id > 0)
            {
                return _productServices.UpdateProduct(id, productEntity);
            }
            return false;
        }

        // DELETE api/product/5
        [DELETE("remove/productid/{id}")]
        [DELETE("clear/productid/{id}")]
        [PUT("delete/productid/{id}")]
        public bool Delete(int id)
        {
            if (id != null && id > 0)
            {
                var isSuccess = _productServices.DeleteProduct(id);
                if (isSuccess)
                {
                    return isSuccess;
                }
                throw new ApiDataException(1002, "Product is already deleted or not exist in system.", HttpStatusCode.NoContent );
            }
            throw new ApiException() {ErrorCode = (int) HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..."};
        }
    }
}
Now you can see, our application is so rich and scalable that none of the exception or transaction can escapelogging.Once setup is inplaced, now you don’t have to worry about writing code each time for logging or requests and exceptions, but you can relax and focus on business logic only.

Conclusion

In this article we learnt about how to perform request logging and exception logging in WebPI. There could be numerous ways in which you can perform these operations but I tried to present this in as simple way as possible. My approach was to take our enterprise level to next level of development, where developers should not always be worried about exception handling and logging. Our solution provides a generic approach of centralizing the operations in one place; all the requests and exceptions are automatically taken care of. In my new articles, I’ll try to enhance the application by explaining unit testing in WebAPI and OData in WebAPI. You can download the complete source code of this article with packages from GitHub. Happy coding Smile | :)

RESTful Day #4: Custom URL Re-Writing/Routing using Attribute Routes in MVC 4 Web APIs


Download Source Code

Introduction

We have already learnt a lot on WebAPI. I have already explained how to create WebAPI, connect it with database using Entity Framework, resolving dependencies using Unity Container as well as using MEF. In all our sample applications we were using default route that MVC provides us for CRUD operations. In this article I’ll explain how to write your own custom routes using Attribute Routing. We’ll deal with Action level routing as well as Controller level routing. I’ll explain this in detail with the help of a sample application. My new readers can use any Web API sample they have, else you can also use the sample applications we developed in my previous articles.
Let’s revisit the road map that I started on Web API,
 Here is my roadmap for learning RESTful APIs,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Routing

Routing in generic terms for any service, API, website is a kind of pattern defining system that tries to maps all request from the clients and resolves that request by providing some response to that request. In WebAPI we can define routes in WebAPIConfig file, these routes are defined in an internal Route Table. We can define multiple sets of Routes in that table.

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,
In our existing application, we created WebAPI with default routes as mentioned in the file named WebApiConfig in App_Start folder of WebApi project. The routes were mentioned in the Register method as,
config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
Do not get confused by MVC routes, since we are using MVC project we also get MVC routes defined inRouteConfig.cs file as,
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
We need to focus on the first one i.e. WebAPI route. As you can see in the following image, what each property signifies,
We have a route name, we have a common URL pattern for all routes, and option to provide optional parameters as well.
Since our application do not have particular different action names, and we were using HTTP VERBS as action names, we didn’t bother much about routes. Our Action names were like,
1. public HttpResponseMessage Get()
2. public HttpResponseMessage Get(int id)
3. public int Post([FromBody] ProductEntity productEntity)
4. public bool Put(int id, [FromBody]ProductEntity productEntity)
5. public bool Delete(int id)

Default route defined does not takes HTTP VERBS action names into consideration and treat them default actions, therefore it does not mentions {action} in routeTemplate. But that’s not limitation, we can have our own routes defined in WebApiConfig, for example, check out the following routes,

  public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.Routes.MapHttpRoute(
               name: "ActionBased",
               routeTemplate: "api/{controller}/{action}/{id}",
               defaults: new { id = RouteParameter.Optional }
           );
            config.Routes.MapHttpRoute(
              name: "ActionBased",
              routeTemplate: "api/{controller}/action/{action}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
        }
And etc. In above mentioned routes, we can have action names as well, if we have custom actions.
So there is no limit to define routes in WebAPI. But there are few limitations to this, note we are talking about WebAPI 1 that we use with .NET Framework 4.0 in Visual Studio 2010. Web API 2 has overcome those limitations by including the solution that I’ll explain in this article. Let’s check out the limitations of these routes,
Yes, these are the limitations that I am talking about in Web API 1.
If we have route template like routeTemplate: “api/{controller}/{id}” or routeTemplate: “api/{controller}/{action}/{id}” or routeTemplate: “api/{controller}/action/{action}/{id}“,
We can never have custom routes and will have to slick to old route convention provided by MVC. Suppose your client of the project wants to expose multiple endpoints for the service, he can’t do so. We also can not have our own defined names for the routes, so lots of limitation.
Let’s suppose we want to have following kind of routes for my web API endpoints, where I can define versions too,
v1/Products/Product/allproducts
v1/Products/Product/productid/1
v1/Products/Product/particularproduct/4
v1/Products/Product/myproduct/
v1/Products/Product/create
v1/Products/Product/update/3
and so on, then we cannot achieve this with existing model.
Fortunately these things have been taken care of in WebAPI 2 with MVC 5, but for this situation we have AttributeRouting to resolve and overcome these limitations.

Attribute Routing

Attribute Routing is all about creating custom routes at controller level, action level. We can have multiple routes using Attribute Routing. We can have versions of routes as well, in short we have the solution for our exiting problems. Let’s straight away jump on how we can implement this in our exising project. I am not explaining on how to create a WebAPI, for that you can refer my first post of the series.
Step 1: Open the solution ,and open Package Manage Console like shown below in the figure,
Goto Tools->Library Packet manage-> Packet Manager Console
 
Step 2: In the package manager console window at left corner of Visual Studio type, Install-Package AttributeRouting.WebApi, and choose the project WebApi or your own API project if you are using any other code sample, then press enter.
 
Step 3: As soon as the package is installed, you’ll get a class named AttributeRoutingHttpConfig.cs in yourApp_Start folder.
This class has its own method to RegisterRoutes, which internally maps attribute routes. It has a start method that picks Routes defined from GlobalConfiguration and calls the RegisterRoutes method,
using System.Web.Http;
using AttributeRouting.Web.Http.WebHost;

[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApi.AttributeRoutingHttpConfig), "Start")]

namespace WebApi 
{
    public static class AttributeRoutingHttpConfig
 {
  public static void RegisterRoutes(HttpRouteCollection routes) 
  {    
   // See http://github.com/mccalltd/AttributeRouting/wiki for more options.
   // To debug routes locally using the built in ASP.NET development server, go to /routes.axd

            routes.MapHttpAttributeRoutes();
  }

        public static void Start() 
  {
            RegisterRoutes(GlobalConfiguration.Configuration.Routes);
        }
    }
}
We don’t even have to touch this class, our custom routes will automatically be taken care of using this class.We just need to focus on defining routes. No coding :-).  You can now use route specific stuff like route names, verbs, constraints, optional parameters, default parameters, methods, route areas, area mappings, route prefixes, route conventions etc.

Setup REST endpoint / WebAPI project to define Routes

Our 90% of the job is done.
We now need to setup or WebAPI project and define our routes.
Our existing ProductController class looks something like shown below,
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BusinessEntities;
using BusinessServices;

namespace WebApi.Controllers
{
    public class ProductController : ApiController
    {

        private readonly IProductServices _productServices;

        #region Public Constructor

        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController(IProductServices productServices)
        {
            _productServices = productServices;
        }

        #endregion

        // GET api/product
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

        // GET api/product/5
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

        // POST api/product
        public int Post([FromBody] ProductEntity productEntity)
        {
            return _productServices.CreateProduct(productEntity);
        }

        // PUT api/product/5
        public bool Put(int id, [FromBody] ProductEntity productEntity)
        {
            if (id > 0)
            {
                return _productServices.UpdateProduct(id, productEntity);
            }
            return false;
        }

        // DELETE api/product/5
        public bool Delete(int id)
        {
            if (id > 0)
                return _productServices.DeleteProduct(id);
            return false;
        }
    }
}
Where we have a controller name Product and Action names as Verbs. When we run the application, we get following type of endpoints only (please ignore port and localhost setting. It’s because I run this application from my local environment),
Get All Products:
Get product By Id:
Create product :
Update product:
Delete product:
Step 1: Add two namespaces to your controller,
using AttributeRouting;
using AttributeRouting.Web.Http;
 

Step 2: Decorate your action with different routes,

Like in above image, I defined a route with name productid which taked id as a parameter. We also have to provide verb (GET, POST, PUT, DELETE, PATCH) along with the route like shown in image. So it is[GET("productid/{id?}")]. You can define whatever route you want for your Action like[GET("product/id/{id?}")], [GET("myproduct/id/{id?}")] and many more.
Now when I run the application and navigate to /help page, I get this,
i.e. I got one more route for Getting product by id. When you’ll test this service you’ll get your desired URL something like: http://localhost:55959/Product/productid/3, that sounds like real REST Smile | :)
Similarly decorate your Action with multiple routes like show below,
        // GET api/product/5
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }
Therefore we see, we can have our custom route names and as well as multiple endpoints for a single Action. That’s exciting.Each endpoint will be different but will serve same set of result.
  • {id?} : here ‘?’ means that parameter can be optional.
  • [GET(“myproduct/{id:range(1, 3)}”)], signifies that the product id’s falling in this range will only be shown.

More Routing Constraints

You can leverage numerous Routing Constraints provided by Attribute Routing. I am taking example of some of them,

Range

To get the product within range, we can define the value, on condition that it should exist in database.
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

Regular Expression

You can use it well for text/string parameters more efficiently.
        [GET(@"id/{e:regex(^[0-9]$)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

e.g. [GET(@"text/{e:regex(^[A-Z][a-z][0-9]$)}")]

Optional Parameters and Default Parameters

You can also mark the service parameters as optional in the route. For example you want to fetch an employee detail from the data base with his name,
[GET("employee/name/{firstname}/{lastname?}")]
public string GetEmployeeName(string firstname, string lastname="mittal")
{
   …………….
  ……………….
}
In the above mentioned code, I marked last name as optional by using question mark ‘?’ to fetch the employee detail. It’s my end user wish to provide the last name or not.
So the above endpoint could be accessed through GET verb with urls,
~/employee/name/akhil/mittal
~/employee/name/akhil
If a route parameter defined is marked optional, you must also provide a default value for that method parameter.
In the above example, I marked ‘lastname’ as an optional one and so provided a default value in the method parameter , if user doesn’t send any value, “mittal” will be used.
In .NET 4.5 Visual Studio > 2010 with WebAPI 2, you can define DefaultRoute as an attribute too, just try it by your own. Use attribute [DefaultRoute] to define default route values.
You can try giving custom routes to all your controller actions.
I marked my actions as,
        // GET api/product
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

        // GET api/product/5
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

        // POST api/product
        [POST("Create")]
        [POST("Register")]
        public int Post([FromBody] ProductEntity productEntity)
        {
            return _productServices.CreateProduct(productEntity);
        }

        // PUT api/product/5
        [PUT("Update/productid/{id}")]
        [PUT("Modify/productid/{id}")]
        public bool Put(int id, [FromBody] ProductEntity productEntity)
        {
            if (id > 0)
            {
                return _productServices.UpdateProduct(id, productEntity);
            }
            return false;
        }

        // DELETE api/product/5
        [DELETE("remove/productid/{id}")]
        [DELETE("clear/productid/{id}")]
        [PUT("delete/productid/{id}")]
        public bool Delete(int id)
        {
            if (id > 0)
                return _productServices.DeleteProduct(id);
            return false;
        }
And therefore get the routes as,

GET

POST / PUT / DELETE

Check for more constraints here.
You must be seeing “v1/Products” in every route, that is due to RoutePrefix I have used at controller level. Let’s discuss RoutePrefix in detail.

RoutePrefix: Routing at Controller level

We were marking our actions with particular route, but guess what, we can mark our controllers too with certain route names, we can achieve this by using RoutePrefix attribute of AttributeRouting. Our controller was named Product, and I want to append Products/Product before my every action, there fore without duplicating the code at each and every action, I can decorate my Controller class with this name like shown below,
    [RoutePrefix("Products/Product")]
    public class ProductController : ApiController
    {
Now, since our controller is marked with this route, it will append the same to every action too. For e.g. route of following action,
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }
Now becomes,
~/Products/Product/allproducts
~/Products/Product/all

RoutePrefix: Versioning

Route prefix can also be used for versioning of the endpoints, like in my code I provided “v1” as version in my RoutePrefix as shown below,
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {
Therefore “v1” will be appended to every route / endpoint of the service. When we release next version, we can certainly maintain a change log separately and mark the endpoint as “v2” at controller level, that will append “v2” to all actions,
e.g.
~/v1/Products/Product/all

~/v2/Products/Product/allproducts
~/v2/Products/Product/all

RoutePrefix: Overriding

This functionality is present in .NET 4.5 with Visual Studio > 2010 with WebAPI 2. You can test it there.
There could be situations that we do not want to use RoutePrefix for each and every action. AttributeRoutingprovides such flexibility too, that despite of RoutePrefix present at controller level, an individual action could have its own route too. It just need to override the default route like shown below,

RoutePrefix at Controller

     [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {

Independent Route of Action

       [Route("~/MyRoute/allproducts")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

Disable Default Routes

You must be wondering that in the list of all the URL’s on service help page, we are getting some different/other routes that we have not defined through attribute routing starting like ~/api/Product. These routes are the outcome of default route provided in WebApiConfig file, remember? If you want to get rid of those unwanted routes, just go and comment everything written in Register method in WebApiConfig.cs file under Appi_Startfolder,
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);
You can also remove the complete Register method, but for that you need to remove its calling too fromGlobal.asax file.

Running the application

Just run the application, we get,
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,

GET

POST

PUT

DELETE

You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service,
Service for Get All products,
Likewise you can test all the service endpoints.

Conclusion

We now know how to define our custom endpoints and what its benefits are. Just to share that this library was introduced by Tim Call, author of http://attributerouting.net and Microsoft has included this in WebAPI 2 by default. My next article will explain token based authentication using ActionFilters in WepAPI. ’til then Happy Coding Smile | :) you can also download the complete source code from GitHub. Add the required packages, if they are missing in the source code.
Click Github Repository to browse for complete source code.

Download Source Code

References

My other series of articles:

RESTful Day #3: Resolve dependency of dependencies using Inversion of Control and dependency injection in ASP.NET Web APIs with Unity Container and Managed Extensibility Framework (MEF)


Download Source Code

Introduction

In my last two articles, I explained how to create a RESTful service using ASP.NET Web API working with Entity Framework and resolving dependencies using Unity Container. In this article, I’ll explain how to create a loosely coupled system with Unity Container and MEF (Managed Extensibility Framework) using Inversion of Control. I’ll not be explaining much theory but rather focus more on practical implementations. For the readers who are following this series, they can use their existing solution that they have created till time. For my new readers of this article, I have provided the download link for the previous source code and current source code as well.
For theory and understanding of DI and IOC you can follow the following links: Unity and Inversion of Control(IOC).

Roadmap

Here is my roadmap for learning RESTful APIs,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,
We tried to design a loosely coupled architecture in the following way,
  • DataModel (responsible for communication with database) : Only talks to service layer.
  • Services (acts as a business logic layer between REST endpoint and data access) : Communicates between REST endpoint and DataModel.
  • REST API i.e. Controllers: Only talks to services via the interfaces exposed.
But when we tried to resolve the dependency of UnitOfWork from Services, we had to reference
DataModel dll in to our WebAPI project; this violated our system like shown in following image,
In this article we’ll try to resolve dependency (data model) of a dependency (services) from our existing solution. My controller depended on services and my services depended on data model. Now we’ll design an architecture in which components will be independent of each other in terms of object creation and instantiation. To achieve this we’ll make use of MEF(Managed Extensibility Framework) along with Unity Container and reflection.
Ideally, we should not be having the below code in our Bootstrapper class,
container.RegisterType().RegisterType(new HierarchicalLifetimeManager());

Managed Extensibility Framework (MEF)

You can have a read about Unity from msdn link. I am just quoting some lines from msdn,

“The Managed Extensibility Framework or MEF is a library for creating lightweight, extensible applications. It allows application developers to discover and use extensions with no configuration required. It also lets extension developers easily encapsulate code and avoid fragile hard dependencies. MEF not only allows extensions to be reused within applications, but across applications as well.”
“MEF is an integral part of the .NET Framework 4, and is available wherever the .NET Framework is used. You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET.”

Creating a Dependency Resolver with Unity and MEF

Open your Visual studio, I am using VS 2010, you can use VS version 2010 or above. Load the solution.
Step 1: Right click solution explorer and add a new project named Resolver,
I have intentionally chosen this name, and you already know it why J
Step 2: Right click Resolver project and click on ManageNugetPackage, in the interface of adding new package, search Unity.MVC3 in online library,
Install the package to your solution.
Step 3: Right click resolver project and add a reference to System.ComponentModel.Composition.
You can find the dll into your GAC.I am using framework 4.0, so referring to the same version dll.
This DLL is the part of MEF and is already installed with .NET Framework 4.0 in the system GAC. This DLL provides classes that are very core of MEF.
Step 4: Just add an interface named IComponent to Resolver project that contains the initialization method named Setup. We’ll try to implement this interface into our Resolver class that we’ll create in our other projects like DataModel, Services and WebApI.
namespace Resolver
{
    /// <summary>
    /// Register underlying types with unity.
    /// </summary>
    public interface IComponent
    {
      
    }
}
Step 5: Before we declare our Setup method, just add one more interface responsible for serving as a contract to register types. I name this interface as IRegisterComponent,
namespace Resolver
{
    /// <summary>
    /// Responsible for registering types in unity configuration by implementing IComponent
    /// </summary>
    public interface IRegisterComponent
    {
        /// <summary>
        /// Register type method
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="withInterception"></param>
        void RegisterType(bool withInterception = false) where TTo : TFrom;
 
        /// <summary>
        /// Register type with container controlled life time manager
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="withInterception"></param>
        void RegisterTypeWithControlledLifeTime(bool withInterception = false) where TTo : TFrom;
    }
}
In this interface I have declared two methods, one RegisterType and other in to RegisterType with Controlled life time of the object, i.e. the life time of an object will be hierarchal in manner. This is kind of same like we do in Unity.
Step 6: Now declare Setup method on our previously created IComponent interface, that takes instance ofIRegisterComponent as a parameter,
void SetUp(IRegisterComponent registerComponent);
So our IComponent interface becomes,
namespace Resolver
{
    /// <summary>
    /// Register underlying types with unity.
    /// </summary>
    public interface IComponent
    {
        void SetUp(IRegisterComponent registerComponent);
    }
}
Step 6: Now we’ll write a packager or you can say a wrapper over MEF and Unity to register types/ components. This is the core MEF implementation. Create a class named ComponentLoader, and add following code to it,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Reflection;
 
namespace Resolver
{
    public static class ComponentLoader
    {
        public static void LoadContainer(IUnityContainer container, string path, string pattern)
        {
            var dirCat = new DirectoryCatalog(path, pattern);
            var importDef = BuildImportDefinition();
            try
            {
                using (var aggregateCatalog = new AggregateCatalog())
                {
                    aggregateCatalog.Catalogs.Add(dirCat);
 
                    using (var componsitionContainer = new CompositionContainer(aggregateCatalog))
                    {
                        IEnumerable exports = componsitionContainer.GetExports(importDef);
 
                        IEnumerable modules =
                            exports.Select(export => export.Value as IComponent).Where(m => m != null);
 
                        var registerComponent = new RegisterComponent(container);
                        foreach (IComponent module in modules)
                        {
                            module.SetUp(registerComponent);
                        }
                    }
                }
            }
            catch (ReflectionTypeLoadException typeLoadException)
            {
                var builder = new StringBuilder();
                foreach (Exception loaderException in typeLoadException.LoaderExceptions)
                {
                    builder.AppendFormat("{0}\n", loaderException.Message);
                }
 
                throw new TypeLoadException(builder.ToString(), typeLoadException);
            }
        }
 
        private static ImportDefinition BuildImportDefinition()
        {
            return new ImportDefinition(
                def => true, typeof(IComponent).FullName, ImportCardinality.ZeroOrMore, false, false);
        }
    }
 
    internal class RegisterComponent : IRegisterComponent
    {
        private readonly IUnityContainer _container;
 
        public RegisterComponent(IUnityContainer container)
        {
            this._container = container;
            //Register interception behaviour if any
        }
 
        public void RegisterType(bool withInterception = false) where TTo : TFrom
        {
            if (withInterception)
            {
                //register with interception
            }
            else
            {
                this._container.RegisterType();
            }
        }
 
        public void RegisterTypeWithControlledLifeTime(bool withInterception = false) where TTo : TFrom
        {
            this._container.RegisterType(new ContainerControlledLifetimeManager());
        }
    }
}
Step 7: Now our Resolver wrapper is ready. Build the project and add its reference to DataModel, BusinessServices and WebApi project like shown below,

Setup Business Services

We already have added reference of Resolver in BusinessServices project. We agreed to implement IComponent interface in each of our project.
So create a class named DependencyResolver and implement IComponent interface into it, we make use of reflection too to import IComponent type. So add a class and add following code to that DependencyResolverclass,
using System.ComponentModel.Composition;
using DataModel;
using DataModel.UnitOfWork;
using Resolver;
 
namespace BusinessServices
{
    [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
 
        }
    }
}
Note that we have implemented SetUp method and in the same method we registered type for my ProductService.
All of the existing code base remains same. We don’t need to touch the IProductServices interface or ProductServices class.

Setup DataModel

We have added Resolver project reference to DataModel project as well. So we’ll try to register the type of UnitOfWork in this project. We proceed in same fashion, just add a DependencyResolver class and implement its Setup method to register type of UnitOfWork. To make the code more readable and standard, I made a change.I just added an interface for UnitOfWork and named it IUnitOfWork. Now my UnitOfWork class derives from this, you can do this exercise in earlier versions of projects we discussed in first two articles.
So my IUnitOfWork contains declaration of a single public method in UnitOfWork,
namespace DataModel.UnitOfWork
{
    public interface IUnitOfWork
    {
        /// <summary>
        /// Save method.
        /// </summary>
        void Save();
    }
}
Now register the type for UnitOfWork in DepenencyResolver class, our class becomes as shown below,
using System.ComponentModel.Composition;
using System.Data.Entity;
using DataModel.UnitOfWork;
using Resolver;
 
namespace DataModel
{
    [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
        }
    }
}
Again, no need to touch any existing code of this project.

Setup REST endpoint / WebAPI project

Our 90% of the job is done.
We now need to setup or WebAPI project. We’ll not add any DependencyResolver class in this project. We’ll invert the calling mechanism of layers in Bootstrapper class that we already have, so when you open your bootstrapper class, you’ll get the code something like,
using System.Web.Http;
using System.Web.Mvc;
using BusinessServices;
using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Unity.Mvc3;
 
namespace WebApi
{
    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();
 
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
 
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
 
            // register all your components with the container here
            // it is NOT necessary to register your controllers
           
            // e.g. container.RegisterType();       
            container.RegisterType().RegisterType(new HierarchicalLifetimeManager());
 
            return container;
        }
    }
}
Now, we need to change the code base a bit to make our system loosely coupled.Just remove the reference of DataModel from WebAPI project.
We don’t want our DataModel to be exposed to WebAPI project, that was our aim though, so we cut down the dependency of DataModel project now.
Add following code of Bootstrapper class to the existing Bootstarpper class,
using System.Web.Http;
//using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Resolver;
using Unity.Mvc3;
 
namespace WebApi
{
    public static class Bootstrapper
    {
        public static void  Initialise()
        {
            var container = BuildUnityContainer();
 
            System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
 
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
 
            // register all your components with the container here
            // it is NOT necessary to register your controllers
           
            // e.g. container.RegisterType();       
           // container.RegisterType().RegisterType(new HierarchicalLifetimeManager());
 
            RegisterTypes(container);
 
            return container;
        }
 
        public static void RegisterTypes(IUnityContainer container)
        {
 
            //Component initialization via MEF
            ComponentLoader.LoadContainer(container, ".\\bin", "WebApi.dll");
            ComponentLoader.LoadContainer(container, ".\\bin", "BusinessServices.dll");
 
        }
    }
}
It is kind of redefining Bootstrapper class without touching our existing controller methods. We now don’t even have to register type for ProductServices as well, we already did this in BusinessServices project.
Note that in RegisterTypes method we load components/dlls through reflection making use of ComponentLoader.We wrote two lines, first to load WebAPI.dll and another one to load Business Services.dll.
Had the name of BusinessServicess.dll be WebAPI.Services.dll, then we would have only written one line of code to load both the WebAPI and BusinessService dll like shown below,
ComponentLoader.LoadContainer(container, ".\\bin", "WebApi*.dll");
Yes we can make use of Regex.

Running the application

Just run the application, we get,
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service,
Service for GetAllProduct,
For Create a new product,
In database, we get new product,
Update product:
We get in database,
Delete product:
In database:

Advantages of this design

In my earlier articles I focussed more on design flaws, but our current design have emerged with few added advantages,
  1. We got an extensible and loosely coupled application design that can go far with more new components added in the same way.
  2. Registering types automatically through reflection. Suppose we want to register any Interface implementation to our REST endpoint, we just need to load that dll in our Bootstrapper class, or if dll’s are of common suffix names then we just have to place that DLL in bin folder, and that will automatically be loaded at run time.
  3. Database transactions or any of such module is now not exposed to the service endpoint, this makes our service more secure and maintains the design structure too.

Conclusion

We now know how to use Unity container to resolve dependency and perform inversion of control using MEF too. In my next article I’ll try to explain how we can open multiple endpoints to our REST service and create custom url’s in the true REST fashion in my WebAPI. Till then Happy Coding Smile | :) You can also download the source code from GitHub. Add the required packages, if they are missing in the source code.

Download Source Code

RESTful Day #2: Inversion of control using dependency injection in Web API’s using Unity Container and Bootstrapper


Introduction

My article will explain how we can make our Web API service architecture loosely coupled and more flexible. We already learnt that how we can create a RESTful service using Asp.net Web API and Entity framework in my last article. If you remember we ended up in a solution with a design flaw, we’ll try to overcome that flaw by resolving the dependencies of dependent components. For those who have not followed my previous article, they can learn by having the sample project attached as a test application from my first article.

There are various methods you can use to resolve dependency of components. In my article I’ll explain how to resolve dependency with the help of Unity Container provided by Microsoft’s Unity Application Block.
We’ll not go into very detailed theory, for theory and understanding of DI and IOC you can follow the following links: Unity and Inversion of Control(IOC). We’ll straight away jump into practical implementation.

Roadmap

Our roadmap for learning RESTful APIs remains same,

I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,
The modules are dependent in a way,
There is no problem with the structure, but the way they interact to each other is really problematic. You must have noticed that we are trying to communicate with layers, making the physical objects of classes.
For e.g.
Controller constructor makes an object of Service layer to communicate,
        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController()
        {
            _productServices =new ProductServices();
        }
Service constructor, in turn, makes and object of UnitOfWork to communicate to database,
        /// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }
The problem lies in these code pieces. We see Controller is dependent upon instantiation of Service and Service is dependent upon UnitOfWork to get instantiated. Our Layers should not be that tightly coupled and should be dependent on each other.
The work of creating object should be assigned to someone else. Our layers should not worry about creating objects.
We’ll assign this role to a third party that will be called our container. Fortunately, Unity provides that help to us, to get rid of this dependency problem and invert the control flow by injecting dependency not by creating objects by new but through constructors or properties. There are other methods too, but I am not going into detail.

Introduction to Unity

You can have a read about Unity from this link; I am just quoting some lines,
“The Unity Application Block (Unity) is a lightweight, extensible dependency injection container that supports constructor injection, property injection, and method call injection. It provides developers with the following advantages:
  • It provides simplified object creation, especially for hierarchical object structures and dependencies, which simplifies application code.
  • It supports abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns.
  • It increases flexibility by deferring component configuration to the container.
  • It has a service location capability; this allows clients to store or cache the container. This is especially useful in ASP.NET Web applications where developers can persist the container in the ASP.NET session or application.”

Setup Unity

Open your Visual studio, I am using VS 2010, You can use VS version 2010 or above. Load the solution.
Step 1: browse to Tools-> Library Packet Manager – > Packet manager Console,
We’ll add package for Unity Application Block.
In the left bottom corner of Visual Studio, You’ll find where to write the command.
Type command Unity.MVC3 and choose “WebApi” project before you fire the command.
Step 2: Bootstrapper class
Unity.MVC3 comes with a Bootstrapper class, as soon as you run the command, the Bootstrapper class will be generated in your solution->WebAPI project,
using System.Web.Http;
using System.Web.Mvc;
using BusinessServices;
using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Unity.Mvc3;

namespace WebApi
{
    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType();        
            container.RegisterType().RegisterType(new HierarchicalLifetimeManager());

            return container;
        }
    }
}
This class comes with an initial configuration to setup your container. All the functionality is inbuilt, we only need to specify the dependencies that we need to resolve in the “BuildUnityContainer“, like it says in the commented statement,
            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType();
Step 3: Just specify the components below these commented lines that we need to resolve. In our case, it’sProductServices and UnitOfWork, so just add,
container.RegisterType().RegisterType(new HierarchicalLifetimeManager());
HierarchicalLifetimeManager” maintains the lifetime of the object and child object depends upon parent object’s lifetime.
If you don’t find “UnitOfWork“, just add reference to DataModel project in WebAPI project.
So our Bootstrapper class becomes,
   public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType();        
            container.RegisterType().RegisterType(new HierarchicalLifetimeManager());

            return container;
        }
Like this we can also specify other dependent objects in BuildUnityContainerMethod.
Step 4: Now we need to call the Initialise method of Bootstrapper class. Note , we need the objects as soon as our modules load, therefore we require the container to do its work at the time of application load, therefore go to Global.asax file and add one line to call Initialise method, since this is a static method, we can directly call it using class name,
Bootstrapper.Initialise();
Our global.asax becomes,
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Newtonsoft.Json;
using WebApi.App_Start;

namespace WebApi
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //Initialise Bootstrapper
            Bootstrapper.Initialise();

            //Define Formatters
            var formatters = GlobalConfiguration.Configuration.Formatters;
            var jsonFormatter = formatters.JsonFormatter;
            var settings = jsonFormatter.SerializerSettings;
            settings.Formatting = Formatting.Indented;
            // settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            var appXmlType = formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
            formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

            //Add CORS Handler
            GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
        }
    }
}
Half of the job is done. We now need to touchbase our controller and Service class constructors to utilize the instances already created for them at application load.

Setup Controller

We have already set up unity in our application. There are various methods in which we can inject dependency, like constructor injection, property injection, via service locator. I am here using Constructor Injection, because I find it best method to use with Unity Container to resolve dependency.
Just go to your ProductController, you find your constructor written as,
        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController()
        {
            _productServices =new ProductServices();
        }
Just add a parameter to your constructor that takes your ProductServices reference, like we did below
       /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController(IProductServices productServices)
        {
            _productServices = productServices;
        }
And initialize your “productServices” variable with the parameter. In this case when the constructor of the controller is called, It will be served with pre-instantiated service instance, and does not need to create an instance of the service, our unity container did the job of object creation.

Setup Services

For services too, we proceed in a same fashion. Just open your ProductServices class, we see the dependency of UnitOfWork here as,
        /// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }
Again, we perform the same steps ,and pass a parameter of type UnitOfWork to our constructor,
Our code becomes,
        /// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices(UnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
Here also we’ll get the pre instantiated object on UnitOfWork. So service does need to worry about creating objects. Remember we did .RegisterType() in Bootstrapper class.
We have now made our components independent.

Running the application

Our job is almost done.We need to run the application, Just hit F5. To our surprise we’ll end up in an error page,
Do you remember we added a test client to our project to test our API in my first article. That test client have a controller too, we need to override its settings to make our application work.Just go to Areas->HelpPage->Controllers->HelpController in WebAPI project like shown below,
Comment out the existing constructors and add a Configuration property like shown below,
      //Remove constructors and existing Configuration property.

        //public HelpController()
        //    : this(GlobalConfiguration.Configuration)
        //{
        //}

        //public HelpController(HttpConfiguration config)
        //{
        //    Configuration = config;
        //}

        //public HttpConfiguration Configuration { get; private set; }

        /// <summary>
        /// Add new Configuration Property
        /// </summary>
        protected static HttpConfiguration Configuration
        {
            get { return GlobalConfiguration.Configuration; }
        }
Our controller code becomes,
using System;
using System.Web.Http;
using System.Web.Mvc;
using WebApi.Areas.HelpPage.Models;

namespace WebApi.Areas.HelpPage.Controllers
{
    /// <summary>
    /// The controller that will handle requests for the help page.
    /// </summary>
    public class HelpController : Controller
    {
        //Remove constructors and existing Configuration property.

        //public HelpController()
        //    : this(GlobalConfiguration.Configuration)
        //{
        //}

        //public HelpController(HttpConfiguration config)
        //{
        //    Configuration = config;
        //}

        //public HttpConfiguration Configuration { get; private set; }

        /// <summary>
        /// Add new Configuration Property
        /// </summary>
        protected static HttpConfiguration Configuration
        {
            get { return GlobalConfiguration.Configuration; }
        }

        public ActionResult Index()
        {
            return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
        }

        public ActionResult Api(string apiId)
        {
            if (!String.IsNullOrEmpty(apiId))
            {
                HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
                if (apiModel != null)
                {
                    return View(apiModel);
                }
            }

            return View("Error");
        }
    }
}
Just run the application, we get,
We alreay have our test client added, but for new readers, I am just again explaining on how to add a test client to our API project.
Just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
You can test each service by clicking on it.
Service for GetAllProduct,
For Create a new product,
In database, we get new product,
Update product:
We get in database,
Delete product:
In database:
Job done.

Design Flaws

What if I say there are still flaws in this design, the design is still not loosely coupled.
Do you remember what we decided while writing our first application?
Our API talks to Services and Services talk to DataModel. We’ll never allow DataModel talk to APIs for security reasons. But did you notice that when we were registering the type in Bootstrapper class, we also registered the type of UnitOfWork that means we added DataModel as a reference to our API project. This is a design breach. We tried to resolve dependency of a dependency by violating our design and compromising security.
In my next article, we’ll overcome this situation, we’ll try to resolve dependency and its dependency without violating our design and compromising security. In fact we’ll make it more secure and loosely coupled.
In my next article we’ll make use of Managed Extensibility Framework(MEF) to achieve the same.

Conclusion

We now know how to use Unity container to resolve dependency and perform inversion of control.
But still there are some flaws in this design. In my next article, I’ll try to make the system more strong. Till then Happy Coding  :-). You can also download the source code from GitHub. Add the required packages, if they are missing in the source code.

RESTful Day #1: Enterprise Level Application Architecture with Web API’s using Entity Framework, Generic Repository Pattern and Unit of Work


Introduction

I have been practicing, reading a lot about RESTful services for past few days. To my surprise I could not find a complete series of practical implementations of ASP.NET Web API’s on the web. My effort in this series will be to focus on how we can develop basic enterprise level application architecture with Web API’s.
We’ll be discussing less theory and doing more practical to understand how RESTful services can be created using an ORM, we choose Entity Framework here. My first article in the series is to set up a basic architecture of REST service based application. Later on in my upcoming articles, I’ll explain how we can follow best standards to achieve enterprise level architecture.

Roadmap

 My road for the series is as follows,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

REST

Here is an extract from Wikipedia,
Unlike SOAP-based web services, there is no “official” standard for RESTful web APIs. This is because REST is an architectural style, while SOAP is a protocol. Even though REST is not a standard per se, most RESTful implementations make use of standards such as HTTP, URI, JSON, and XML.
I agree to it . Let’s do some coding.

Setup database

I am using SQL Server 2008 as a database server. I have provided the sql scripts to create the database in Sql Server, you can use the same to create one.I have given WebApiDb as my database name. My database contains three tables for now, Products, Tokens, User. In this tutorial we’ll only be dealing with product table to perform CURD operations using Web API and Entity framework. We’ll use Tokens and User in my upcoming article. For those who fail to create database through scripts, here is the structure you can follow,

Web API project

Open your Visual Studio, I am using VS 2010, You can use VS version 2010 or above.
Step 1: Create a new Project in your visual studio,
Step 2: There after choose to create ASP.NET MVC 4 Web application, and give it a name of your choice, I gave itWebAPI.
Step 3: Out of different type of project templates shown to you, choose Web API project,
Once done, you’ll get a project structure like shown below, with a default Home and Values controller.
You can choose to delete this ValuesController, as we’ll be using our own controller to learn.

Setup Data Access Layer

Let’s setup or data access layer first. We’ll be using Entity Framework 5.0 to talk to database. We’ll use Generic Repository Pattern and Unit of work pattern to standardize our layer.
Let’s have a look at the standard definition of Entity Framework given by Microsoft:
“The Microsoft ADO.NET Entity Framework is an Object/Relational Mapping (ORM) framework that enables developers to work with relational data as domain-specific objects, eliminating the need for most of the data access plumbing code that developers usually need to write. Using the Entity Framework, developers issue queries using LINQ, then retrieve and manipulate data as strongly typed objects. The Entity Framework’s ORM implementation provides services like change tracking, identity resolution, lazy loading, and query translation so that developers can focus on their application-specific business logic rather than the data access fundamentals.”
In simple language, Entity framework is an Object/Relational Mapping (ORM) framework. It is an enhancement to ADO.NET, an upper layer to ADO.NET that gives developers an automated mechanism for accessing and storing the data in the database.
Step 1 : Create a new class library in your visual studio, and name it DataModel as shown below,
Step2: In the same way, create one more project i.e. again a class library and call it BusinessEntities,
I’ll explain the use of this class library soon.
Step 3: Move on to your DataModel project , right click on it and add a new item, in the list shown, choose ADO.NET Data Model, and name it WebApiDataModel.edmx.
The file .edmx will contain the database information of our database that we created earlier, let’s set up this. You’ll be presented a wizard like follows,
Choose, generate from database. Choose Microsoft SQl Server like shown in the following image,
Click continue, then provide the credentials of your database, i.e. WebAPIdb, and connect it,
You’ll get a screen, showing the connection string of the database we chose,
Provide the name of the connection string as WebApiDbEntities and click Next.
Choose all the database objects, check all the check boxes, and provide a name for the model. I gave it a name WebApiDbModel.
Once you finish this wizard, you’ll get the schema ready in your datamodel project as follows,
We’ve got our schema in-place using Entity Framework. But few work is still remaining. We need our data context class and entities through which we’ll communicate with database.
So, moving on to next step.
Step 3: Click on tools in Visual Studio and open Extension manager. We need to get db context generator for our datamodel. We can also do it using default code generation item by right clicking in the edmx view and add code generation item, but that will generate object context class and that is heavier than db context. I want light weighted db context class to be created, so we’ll use extension manager to add a package and then create a db context class.
Search for Entity Framework Dbcontext generator in online gallery and select the one for EF 5.x like below,
I guess you need to restart Visual studio to get that into your templates.
Step 4 : Now right click in the .edmx file schema designer and choose “Add Code Generation Item..”.
Step 5 : Now you’ll see that we have got the template for the extension that we added, select that EF 5.x DbContext Generator and click Add.
After adding this we’ll get the db context class and its properties, this class is responsible for all database transactions that we need to perform, so our structure looks like as shown below,
Wow, we ended up in errors. But we got our db context class and our entity models, You can see them in our DataModel project. Errors? Nothing to worry about, it’s just we did not reference entity framework in our project. We’ll do it right away.
Step 6 : Go to Tools -> Library Packet Manager->Packet manager Console. You’ll get the console in left bottom of Visual studio.
Select dataModel project and write a command “Install-Package EntityFramework –Version 5.0.0” to install Entity Framework 5 in our DataModel project.
Press enter. And all the errors get resolved.

Generic Repository and Unit of Work

You can read about repository pattern and creating a repository in detail from my article :https://codeteddy.com/2013/09/03/learning-mvc-part-5repository-pattern-in-mvc3-application-with-entity-framework/.
Just to list down the benefits of Repository pattern,
  • It centralizes the data logic or Web service access logic.
  • It provides a substitution point for the unit tests.
  • It provides a flexible architecture that can be adapted as the overall design of the application evolves.
We’ll create a generic repository that works for all our entities. Creating repositories for each and every entity may result in lots of duplicate code in large projects.For creating Generic Repository you can follow : https://codeteddy.com/2013/09/03/learning-mvc-part-6-generic-repository-pattern-in-mvc3-application-with-entity-framework/
Step 1: Add a folder named GenericRepository in DataModel project and to that folder add a class named Generic Repository. Add following code to that class, that servers as a template based generic code for all the entities that will interact with database,
#region Using Namespaces...

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;

#endregion

namespace DataModel.GenericRepository
{
/// <summary>
    /// Generic Repository class for Entity Operations
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class GenericRepository where TEntity : class
    {
#region Private member variables...
internal WebApiDbEntities Context;
internal DbSet DbSet;
#endregion

#region Public Constructor...
/// <summary>
        /// Public Constructor,initializes privately declared local variables.
        /// </summary>
        /// <param name="context"></param>
        public GenericRepository(WebApiDbEntities context)
        {
this.Context = context;
this.DbSet = context.Set();
        }
#endregion

#region Public member methods...

/// <summary>
        /// generic Get method for Entities
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable Get()
        {
            IQueryable query = DbSet;
return query.ToList();
        }

/// <summary>
        /// Generic get method on the basis of id for Entities.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual TEntity GetByID(object id)
        {
return DbSet.Find(id);
        }

/// <summary>
        /// generic Insert method for the entities
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Insert(TEntity entity)
        {
            DbSet.Add(entity);
        }

/// <summary>
        /// Generic Delete method for the entities
        /// </summary>
        /// <param name="id"></param>
        public virtual void Delete(object id)
        {
            TEntity entityToDelete = DbSet.Find(id);
            Delete(entityToDelete);
        }

/// <summary>
        /// Generic Delete method for the entities
        /// </summary>
        /// <param name="entityToDelete"></param>
        public virtual void Delete(TEntity entityToDelete)
        {
if (Context.Entry(entityToDelete).State == EntityState.Detached)
            {
                DbSet.Attach(entityToDelete);
            }
            DbSet.Remove(entityToDelete);
        }

/// <summary>
        /// Generic update method for the entities
        /// </summary>
        /// <param name="entityToUpdate"></param>
        public virtual void Update(TEntity entityToUpdate)
        {
            DbSet.Attach(entityToUpdate);
            Context.Entry(entityToUpdate).State = EntityState.Modified;
        }

/// <summary>
        /// generic method to get many record on the basis of a condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual IEnumerable GetMany(Func<TEntity, bool> where)
        {
return DbSet.Where(where).ToList();
        }

/// <summary>
        /// generic method to get many record on the basis of a condition but query able.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual IQueryable GetManyQueryable(Func<TEntity, bool> where)
        {
return DbSet.Where(where).AsQueryable();
        }

/// <summary>
        /// generic get method , fetches data for the entities on the basis of condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public TEntity Get(Func<TEntity, Boolean> where)
        {
return DbSet.Where(where).FirstOrDefault();
        }

/// <summary>
        /// generic delete method , deletes data for the entities on the basis of condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public void Delete(Func<TEntity, Boolean> where)
        {
            IQueryable objects = DbSet.Where(where).AsQueryable();
foreach (TEntity obj in objects)
                DbSet.Remove(obj);
        }

/// <summary>
        /// generic method to fetch all the records from db
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable GetAll()
        {
return DbSet.ToList();
        }

/// <summary>
        /// Inclue multiple
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="include"></param>
        /// <returns></returns>
        public IQueryable GetWithInclude(
            System.Linq.Expressions.Expression<Func<TEntity, 
bool>> predicate, params string[] include)
        {
            IQueryable query = this.DbSet;
            query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.Where(predicate);
        }

/// <summary>
        /// Generic method to check if entity exists
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns></returns>
        public bool Exists(object primaryKey)
        {
return DbSet.Find(primaryKey) != null;
        }

/// <summary>
        /// Gets a single record by the specified criteria (usually the unique identifier)
        /// </summary>
        /// <param name="predicate">Criteria to match on</param>
        /// <returns>A single record that matches the specified criteria</returns>
        public TEntity GetSingle(Func<TEntity, bool> predicate)
        {
return DbSet.Single(predicate);
        }

/// <summary>
        /// The first record matching the specified criteria
        /// </summary>
        /// <param name="predicate">Criteria to match on</param>
        /// <returns>A single record containing the first record matching the specified criteria</returns>
        public TEntity GetFirst(Func<TEntity, bool> predicate)
        {
return DbSet.First(predicate);
        }


#endregion
    }
}

Unit of Work

Again I’ll not explain in detail what Unit of Work is. You can google about the theory or follow my existing article on MVC with Unit of Work.
To give a heads up, again from my existing article, the important responsibilities of Unit of Work are,
  • To manage transactions.
  • To order the database inserts, deletes, and updates.
  • To prevent duplicate updates. Inside a single usage of a Unit of Work object, different parts of the code may mark the same Invoice object as changed, but the Unit of Work class will only issue a single UPDATE command to the database.
The value of using a Unit of Work pattern is to free the rest of our code from these concerns so that you can otherwise concentrate on business logic.
Step 1: Create a folder named UnitOfWork, add a class to that folder named UnitOfWork.cs,
Add GenericRepository properties for all the three entities that we got. The class also implementsIDisposableinterface and it’s method Dispose to free up connections and objects. The class will be as follows,
#region Using Namespaces...

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Entity.Validation;
using DataModel.GenericRepository;

#endregion

namespace DataModel.UnitOfWork
{
/// <summary>
    /// Unit of Work class responsible for DB transactions
    /// </summary>
    public class UnitOfWork : IDisposable
    {
#region Private member variables...

private WebApiDbEntities _context = null;
private GenericRepository _userRepository;
private GenericRepository _productRepository;
private GenericRepository _tokenRepository;
#endregion

public UnitOfWork()
        {
            _context = new WebApiDbEntities();
        }

#region Public Repository Creation properties...

/// <summary>
        /// Get/Set Property for product repository.
        /// </summary>
        public GenericRepository ProductRepository
        {
get
            {
if (this._productRepository == null)
this._productRepository = new GenericRepository(_context);
return _productRepository;
            }
        }

/// <summary>
        /// Get/Set Property for user repository.
        /// </summary>
        public GenericRepository UserRepository
        {
get
            {
if (this._userRepository == null)
this._userRepository = new GenericRepository(_context);
return _userRepository;
            }
        }

/// <summary>
        /// Get/Set Property for token repository.
        /// </summary>
        public GenericRepository TokenRepository
        {
get
            {
if (this._tokenRepository == null)
this._tokenRepository = new GenericRepository(_context);
return _tokenRepository;
            }
        }
#endregion

#region Public member methods...
/// <summary>
        /// Save method.
        /// </summary>
        public void Save()
        {
try
            {
                _context.SaveChanges();
            }
catch (DbEntityValidationException e)
            {

var outputLines = new List<string>();
foreach (var eve in e.EntityValidationErrors)
                {
                    outputLines.Add(string.Format(
"{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", DateTime.Now, 
                        eve.Entry.Entity.GetType().Name, eve.Entry.State));
foreach (var ve in eve.ValidationErrors)
                    {
                        outputLines.Add(string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
                    }
                }
                System.IO.File.AppendAllLines(@"C:\errors.txt", outputLines);

throw e;
            }

        }

#endregion

#region Implementing IDiosposable...

#region private dispose variable declaration...
private bool disposed = false; 
#endregion

/// <summary>
        /// Protected Virtual Dispose method
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
if (!this.disposed)
            {
if (disposing)
                {
                    Debug.WriteLine("UnitOfWork is being disposed");
                    _context.Dispose();
                }
            }
this.disposed = true;
        }

/// <summary>
        /// Dispose method
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        } 
#endregion
    }
}
Now we have completely set up our data access layer, and our project structure looks like as shown below,

Setup Business Entities

Remember, we created a business entities project. You may wonder, we already have database entities to interact with database then why do we need Business Entities? The answer is as simple as that, we are trying to follow a proper structure of communication, and one would never want to expose the database entities to the end client, in our case is Web API, it involves lot of risk. Hackers may manipulate the details and get accessto your database.Instead we’ll use database entities in our business logic layer and use Business Entities as transfer objects to communicate between business logic and Web API project. So business entities may have different names but, their properties remains same as database entities. In our case we’ll add same name business entity classes appendint word “Entity” to them in our BusinessEntity project. So we’ll end up having three classes as follows,

Product entity

public class ProductEntity
    {
public int ProductId { get; set; }
public string ProductName { get; set; }
    }

Token entity

public class TokenEntity
    {
public int TokenId { get; set; }
public int UserId { get; set; }
public string AuthToken { get; set; }
public System.DateTime IssuedOn { get; set; }
public System.DateTime ExpiresOn { get; set; }
    }

User entity

public class UserEntity
    {
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Name { get; set; }
    }

Setup Business Services Project

Add a new class library to the solution named BusinessServices. This layer will act as our business logic layer. Note that, we can make use of our API controllers to write business logic, but I am trying to segregate my business logic in an extra layer so that if in future I want to use WCF, MVC, ASP.NET Web Pages or any other application as my presentation layer then I can easily integrate my Business logic layer in it.
We’ll make this layer testable, so we need to create an interface in and declare CURD operations that we need to perform over product table.Before we proceed, add the reference of BusinessEntities project and DataModel project to this newly created project
Step 1 : Create an interface named IProductServices and add following code to it for CURD operations methods,
using System.Collections.Generic;
using BusinessEntities;

namespace BusinessServices
{
/// <summary>
    /// Product Service Contract
    /// </summary>
    public interface IProductServices
    {
        ProductEntity GetProductById(int productId);
        IEnumerable GetAllProducts();
int CreateProduct(ProductEntity productEntity);
bool UpdateProduct(int productId,ProductEntity productEntity);
bool DeleteProduct(int productId);
    }
}
Step 2 : Create a class to implement this interface.name that class ProductServices,
The class contains a private variable of UnitOfWork and a constructor to initialize that variable,
private readonly UnitOfWork _unitOfWork;

/// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }
We have decided not to expose our db entities to Web API project, so we need something to map the db entities data to my business entity classes. We’ll make use of AutoMapper.You can read about AutoMapper in my this article.
Step 3: Just right click project-> Extension manager, search for AutoMapper in online galary and add to BusinessServices project,
Step 4: Implement methods in ProductServices class,
Add following code to the class,
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using AutoMapper;
using BusinessEntities;
using DataModel;
using DataModel.UnitOfWork;

namespace BusinessServices
{
/// <summary>
    /// Offers services for product specific CRUD operations
    /// </summary>
    public class ProductServices:IProductServices
    {
private readonly UnitOfWork _unitOfWork;

/// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }

/// <summary>
        /// Fetches product details by id
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public BusinessEntities.ProductEntity GetProductById(int productId)
        {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
            {
                Mapper.CreateMap();
var productModel = Mapper.Map(product);
return productModel;
            }
return null;
        }

/// <summary>
        /// Fetches all the products.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetAllProducts()
        {
var products = _unitOfWork.ProductRepository.GetAll().ToList();
if (products.Any())
            {
                Mapper.CreateMap();
var productsModel = Mapper.Map<List, List>(products);
return productsModel;
            }
return null;
        }

/// <summary>
        /// Creates a product
        /// </summary>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public int CreateProduct(BusinessEntities.ProductEntity productEntity)
        {
using (var scope = new TransactionScope())
            {
var product = new Product
                {
                    ProductName = productEntity.ProductName
                };
                _unitOfWork.ProductRepository.Insert(product);
                _unitOfWork.Save();
                scope.Complete();
return product.ProductId;
            }
        }

/// <summary>
        /// Updates a product
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public bool UpdateProduct(int productId, BusinessEntities.ProductEntity productEntity)
        {
var success = false;
if (productEntity != null)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {
                        product.ProductName = productEntity.ProductName;
                        _unitOfWork.ProductRepository.Update(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }

/// <summary>
        /// Deletes a particular product
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public bool DeleteProduct(int productId)
        {
var success = false;
if (productId > 0)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {

                        _unitOfWork.ProductRepository.Delete(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }
    }
}
Let me explain the idea of the code. We have 5 methods as follows,
  1. To get product by id ( GetproductById ) : We call repository to get the product by id. Id comes as a parameter from the calling method to that service method. It returns the product entity from the database. Note that it will not return the exact db entity, instead we’ll map it with our business entity usingAutoMapper and return it to calling method.
    /// <summary>
            /// Fetches product details by id
            /// </summary>
            /// <param name="productId"></param>
            /// <returns></returns>
            public BusinessEntities.ProductEntity GetProductById(int productId)
            {
    var product = _unitOfWork.ProductRepository.GetByID(productId);
    if (product != null)
                {
                    Mapper.CreateMap();
    var productModel = Mapper.Map(product);
    return productModel;
                }
    return null;
            }
  2. Get all products from database (GetAllProducts) : This method returns all the products residing in database, again we make use of AutoMapper to map the list and return back.
    /// <summary>
            /// Fetches all the products.
            /// </summary>
            /// <returns></returns>
            public IEnumerable GetAllProducts()
            {
    var products = _unitOfWork.ProductRepository.GetAll().ToList();
    if (products.Any())
                {
                    Mapper.CreateMap();
    var productsModel = Mapper.Map<List, List>(products);
    return productsModel;
                }
    return null;
            }
  3. Create a new product (CreateProduct) : This method takes productBusinessEntity as an argument and creates a new object of actual database entity and insert it using unit of work.
    /// <summary>
            /// Creates a product
            /// </summary>
            /// <param name="productEntity"></param>
            /// <returns></returns>
            public int CreateProduct(BusinessEntities.ProductEntity productEntity)
            {
    using (var scope = new TransactionScope())
                {
    var product = new Product
                    {
                        ProductName = productEntity.ProductName
                    };
                    _unitOfWork.ProductRepository.Insert(product);
                    _unitOfWork.Save();
                    scope.Complete();
    return product.ProductId;
                }
            }
I guess you can now write update and delete methods. So I am writing the code of complete class,
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using AutoMapper;
using BusinessEntities;
using DataModel;
using DataModel.UnitOfWork;

namespace BusinessServices
{
/// <summary>
    /// Offers services for product specific CRUD operations
    /// </summary>
    public class ProductServices:IProductServices
    {
private readonly UnitOfWork _unitOfWork;

/// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }

/// <summary>
        /// Fetches product details by id
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public BusinessEntities.ProductEntity GetProductById(int productId)
        {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
            {
                Mapper.CreateMap();
var productModel = Mapper.Map(product);
return productModel;
            }
return null;
        }

/// <summary>
        /// Fetches all the products.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetAllProducts()
        {
var products = _unitOfWork.ProductRepository.GetAll().ToList();
if (products.Any())
            {
                Mapper.CreateMap();
var productsModel = Mapper.Map<List, List>(products);
return productsModel;
            }
return null;
        }

/// <summary>
        /// Creates a product
        /// </summary>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public int CreateProduct(BusinessEntities.ProductEntity productEntity)
        {
using (var scope = new TransactionScope())
            {
var product = new Product
                {
                    ProductName = productEntity.ProductName
                };
                _unitOfWork.ProductRepository.Insert(product);
                _unitOfWork.Save();
                scope.Complete();
return product.ProductId;
            }
        }

/// <summary>
        /// Updates a product
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public bool UpdateProduct(int productId, BusinessEntities.ProductEntity productEntity)
        {
var success = false;
if (productEntity != null)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {
                        product.ProductName = productEntity.ProductName;
                        _unitOfWork.ProductRepository.Update(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }

/// <summary>
        /// Deletes a particular product
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public bool DeleteProduct(int productId)
        {
var success = false;
if (productId > 0)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {

                        _unitOfWork.ProductRepository.Delete(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }
    }
}
Job done at business service level. Let’s move on to API controller to call these methods.

Setup WebAPI project

Step1 : Just add the reference of BusinessEntity and BusinessService in the WebAPI project, our architecture becomes like this,
Step 2: Add a new WebAPI controller in Controller folder. Right click Controller folder and add a new controller.
We get a controller as follows,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace WebApi.Controllers
{
public class ProductController : ApiController
    {
// GET api/product
        public IEnumerable<string> Get()
        {
return new string[] { "value1", "value2" };
        }

// GET api/product/5
        public string Get(int id)
        {
return "value";
        }

// POST api/product
        public void Post([FromBody]string value)
        {
        }

// PUT api/product/5
        public void Put(int id, [FromBody]string value)
        {
        }

// DELETE api/product/5
        public void Delete(int id)
        {
        }
    }
}
We get HTTP VERBS as method names. Web API is smart enough to recognize request with the name of the VERB itself. In our case we are doing CRUD operations, so we don’t need to change the names of the method, we just needed this. We only have to write calling logic inside these methods. In my upcoming articles of the series, we will figure out how we can define new routes and provide method names of our choice with those routes.
Step 3: Add logic to call Business Service methods, just make an object of Business Service and call its respective methods, our Controller class becomes like,
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BusinessEntities;
using BusinessServices;

namespace WebApi.Controllers
{
public class ProductController : ApiController
    {

private readonly IProductServices _productServices;

#region Public Constructor

/// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController()
        {
            _productServices =new ProductServices();
        }

#endregion

// GET api/product
        public HttpResponseMessage Get()
        {
var products = _productServices.GetAllProducts();
if (products != null)
            {
var productEntities = products as List ?? products.ToList();
if (productEntities.Any())
return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            }
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

// GET api/product/5
        public HttpResponseMessage Get(int id)
        {
var product = _productServices.GetProductById(id);
if (product != null)
return Request.CreateResponse(HttpStatusCode.OK, product);
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

// POST api/product
        public int Post([FromBody] ProductEntity productEntity)
        {
return _productServices.CreateProduct(productEntity);
        }

// PUT api/product/5
        public bool Put(int id, [FromBody]ProductEntity productEntity)
        {
if (id  > 0)
            {
return _productServices.UpdateProduct(id, productEntity);
            }
return false;
        }

// DELETE api/product/5
        public bool Delete(int id)
        {
if (id > 0)
return _productServices.DeleteProduct(id);
return false;
        }
    }
}
Just run the application, we get,
But now how do we test our API? We don’t have client. Guys, we’ll not be writing a client now to test it.We’ll add a package that will do all our work.
Just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,

Running the Application

Before running the application, I have put some test data in our product table.
Just hit F5, you get the same page as you got earlier, just append “/help” in its url, and you’ll get the test client,
You can test each service by clicking on it.
Service for GetAllProduct,
For Create a new product,
In database, we get new product,
Update product:
We get in database,
Delete product:
In database:
Job done.

Design Flaws

  1. Architecture is tightly coupled. IOC (Inversion of Control) needs to be there.
  2. We cannot define our own routes.
  3. No exception handling and logging.
  4. No unit tetsts.

Conclusion

We now know how to create a WebAPI and perform CRUD operations using n layered architecture.
But still there are some flaws in this design.In my next two articles I’ll explain how to make the system loosely coupled using Dependency Injection Principle. We’ll also cover all the design flaws to make our design better and stronger. Till then Happy Coding J You can also download the source code from GitHub.