ASP MVC, C#

ASP MVC 4 : WEBAPI / UNITOFWORK / RESPOSITORY AND IOC

A while back I published an article which discussed how to use the then WCF web API with UnitOfWork/Respository, and one user asked me how to do this with ASP MVC4, where the WCF Web API has now become the WebAPI, which you can use by creating a new ApiController. Its pretty simple. To do this lets consider a simple ApiController which is as follows:

public class ProductsController : ApiController
{
    private readonly IUnitOfWork unitOfWork;
    private readonly IRepository productRepository;

    public ProductsController(IUnitOfWork unitOfWork, IRepository productRepository)
    {
        if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); }
        if (productRepository == null) { throw new ArgumentNullException("productRepository"); }

        this.unitOfWork = unitOfWork;
        this.productRepository = productRepository;
    }

    public IEnumerable GetAllProducts()
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        return productRepository.FindAll().AsEnumerable();
    }

    public Product GetProduct(int id)
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        Product item = productRepository.FindBy(x => x.Id == id).SingleOrDefault();
        if (item == null)
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }
        return item;
    }

    public IEnumerable GetProductsByCategory(string category)
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        return productRepository.FindBy(x=> string.Equals(x.Category, category, StringComparison.OrdinalIgnoreCase));
    }

    public HttpResponseMessage PostProduct(Product item)
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        Product newItem = productRepository.Add(item);
        unitOfWork.Commit();
        var response = Request.CreateResponse(HttpStatusCode.Created, newItem);
        string uri = Url.Link("DefaultApi", new { id = item.Id });
        response.Headers.Location = new Uri(uri);
        return response;
    }

    public void PutProduct(int id, Product product)
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        Product item = productRepository.FindBy(x => x.Id == id).SingleOrDefault();
        if (item != null)
        {
            item.Name = product.Name;
            item.Category = product.Category;
            item.Price = product.Price;
            unitOfWork.Commit();
        }
    }

    public HttpResponseMessage DeleteProduct(int id)
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        Product item = productRepository.FindBy(x => x.Id == id).SingleOrDefault();
        if (item != null)
        {
            productRepository.Remove(item);
            unitOfWork.Commit();
        }
        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }

}

Where you can clearly see this guy takes some dependenices which look like this

UnitOfWork
I am using a Entity Framework code first Unit of work abstraction. The general idea I was going for is that my repositories can involve in a UnitOfWork, and the UnitOfWork is committed when the work is well um done.

public interface IUnitOfWork : IDisposable
{
    void Commit();
    void Attach(T obj) where T : class;
    void Add(T obj) where T : class;
    IQueryable Get() where T : class;
    bool Remove(T item) where T : class;
}
public abstract class EfDataContextBase : DbContext, IUnitOfWork
{
    public IQueryable Get() where T : class
    {
        return Set();
    }

    public bool Remove(T item) where T : class
    {
        try
        {
            Set().Remove(item);
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }

    public void Commit()
    {
        base.SaveChanges();
    }

    public void Attach(T obj) where T : class
    {
        Set().Attach(obj);
    }

    public void Add(T obj) where T : class
    {
        Set().Add(obj);
    }
}
public class ProductContext : EfDataContextBase, IUnitOfWork
{
    public DbSet Products { get; set; }
}

Repository
I went for a generic repository, but you may find that you do need a specific repository if these simple methods do not satisfy your needs.

public interface IRepository where T : class
{
    void EnrolInUnitOfWork(IUnitOfWork unitOfWork);
    int Count { get; }
    T Add(T item);
    bool Contains(T item);
    void Remove(T item);
    IQueryable FindAll();
    IQueryable FindBy(Func<T, bool> predicate);
}
public class Repository : IRepository where T : class
{
    protected IUnitOfWork context;

    public void EnrolInUnitOfWork(IUnitOfWork unitOfWork)
    {
        this.context = unitOfWork;
    }

    public int Count
    {
        get { return context.Get().Count(); }
    }

    public T Add(T item)
    {
        context.Add(item);
        return item;
    }

    public bool Contains(T item)
    {
        return context.Get().FirstOrDefault(t => t == item) != null;
    }

    public void Remove(T item)
    {
        context.Remove(item);
    }

    public IQueryable FindAll()
    {
        return context.Get();
    }

    public IQueryable FindBy(Func<T, bool> predicate)
    {
        return context.Get().Where(predicate).AsQueryable();
    }
}

 

So how do these get satisfied?

Well that is pretty simple, we just need to have a MVC 4 IDependencyScope/IDependencyResolver inheriting class which looks like this. The important thing to note here is that we are creating a new container to service the request for the scope that we get told about by inheriting from IDependencyScope. I went with this approach rather than child containers, which are deprecated in Castle now. I also went for Castle due to its support for open generics, which I needed to have a single generic repository.

class CastleScopeContainer : IDependencyScope, IDependencyResolver
{
    protected IWindsorContainer container;

    public IDependencyScope BeginScope()
    {
        container = new WindsorContainer().Install(new[] { new ApiInstaller() }); ;
        return this;
    }


    public object GetService(Type serviceType)
    {
        try
        {
            return container.Resolve(serviceType);
        }
        catch(Exception ex)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            var results = container.ResolveAll(serviceType);
            if (results == null)
                return new List<object>();

            return results.Cast<object>();
        }
        catch(Exception ex)
        {
            return new List<object>();
        }

    }

    public void Dispose()
    {
        container.Dispose();
    }
}

Where we configure a standard Castle Windsor IOC container using the following installer(s)

public class ApiInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        container.Register
        (
            Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>)).LifestyleTransient(),
            Component.For().ImplementedBy().LifestyleTransient(),
            Component.For().LifestyleTransient()
        );
    }
}
public class DDDInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        container.Register
        (
            Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>)).LifestyleTransient(),
            Component.For().ImplementedBy().LifestyleTransient()
        );
    }
}

And the following Global.asax.cs which is used to setup all the IOC requirements for both the WebApi and the ControllerFactory

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

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        #region IOC
        //IOC : I like Castle because it has open generics

        //Web Api
        GlobalConfiguration.Configuration.DependencyResolver = new CastleScopeContainer();

        //Controllers
        IWindsorContainer container = new ContainerFactory().Install(
                        new DDDInstaller(),
                        new ControllerInstaller()
                    );
        ControllerBuilder.Current.SetControllerFactory(new CastleControllerFactory(container));
        #endregion

        //Seed database
        Database.SetInitializer(new ProductInitializer());

    }
}

We can also run a standard controller using IOC, which is easily achievable using a ControllerFactory something like the following:

public class CastleControllerFactory : DefaultControllerFactory
{
    private readonly IWindsorContainer container;

    public CastleControllerFactory(IWindsorContainer container)
    {
        this.container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return base.GetControllerInstance(requestContext, null);
        }

        object controller= container.Resolve(controllerType);
        if (controller != null)
        {
            return (IController)controller;
        }

        return base.GetControllerInstance(requestContext, null);
    }

    public override void ReleaseController(IController controller)
    {
        var disposable = controller as IDisposable;

        if (disposable != null)
        {
            disposable.Dispose();
        }
        container.Release(controller);
    }
}

Where the ControllerInstaller we previously used in global.asax.cs looks like this

public class ControllerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            AllTypes.FromAssembly(Assembly.GetExecutingAssembly())
                .BasedOn().LifestylePerWebRequest());
    }
}

Where we may have a controller that looks like this, where we also have the goodness of IOC resolves dependencies in our controllers.

public class HomeController : Controller
{
    private readonly IUnitOfWork unitOfWork;
    private readonly IRepository productRepository;

    public HomeController(IUnitOfWork unitOfWork, IRepository productRepository)
    {
        if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); }
        if (productRepository == null) { throw new ArgumentNullException("productRepository"); }

        this.unitOfWork = unitOfWork;
        this.productRepository = productRepository;
    }

    private IEnumerable GetAllProducts()
    {
        productRepository.EnrolInUnitOfWork(unitOfWork);
        return productRepository.FindAll().AsEnumerable();
    }

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult ShowDetails()
    {
        ViewData["products"] = string.Format("There are currently {0} Products", GetAllProducts().Count());
        return View();
    }
}

I havea small demo project which shows a work demo of all of this available at : http://dl.dropbox.com/u/2600965/Blogposts/2012/07/ProductStoreMVC4Demo.zip

Advertisements
Uncategorized

DSLs : A deep(ish) dive

It has been a while since I have written a full article, which is cool, as I have been taking some time off to read a few books. One of these books was Martin Fowlers DSL book, which inspired me to have a play around with DSLs a bit more. To this end I have just published an article on how to create internal DSLs, which you can read about here :

http://www.codeproject.com/Articles/426362/DSLs-A-Deep-ish-look

 

Hope there is something of interest for you in there.