Monday, February 27, 2012

Using StructureMap with Web API

To inject dependencies into your ASP.NET Web API controller we need to use the Web API dependency resolver. It is similar to the MVC 3 IDependencyResolver interface definition.

In the blog post I'll create a custom dependency resolver using StructureMap.

Firstly we need to create a class that inherits from IDependencyResolver which resides in the namespace System.Web.Http.Services.



Code Snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Services;
using StructureMap;

namespace WebApi.Dependency
{
    public class StructureMapDependencyResolver:IDependencyResolver
    {
        public StructureMapDependencyResolver(IContainer container)
        {
            _container = container;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType.IsAbstract || serviceType.IsInterface)
                return _container.TryGetInstance(serviceType);

            return _container.GetInstance(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
        }

        private readonly IContainer _container;
    }
}



To register this with Web Api we use the Global.asax file with the Application_Start method insert the following code.


Code Snippet

var container = ObjectFactory.Container;
            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
                new StructureMapDependencyResolver(container));



so that the Application_Start method looks like


Code Snippet

        protected void Application_Start()
        {

            var container = ObjectFactory.Container;
            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
                new StructureMapDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            BundleTable.Bundles.RegisterTemplateBundles();
        }



Now we can have controllers that use dependency injection.




Code Snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using NHibernate.Linq;
using WebApi.Data.Configuration;
using WebApi.Data.Models;

namespace WebApi.Controllers
{
    public class WorkoutController : ApiController
    {
        private readonly IUnitOfWork _unitOfWork;

        public WorkoutController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        // GET /api/workouts
        public IEnumerable<Workout> Get()
        {
            return _unitOfWork.CurrentSession.Query<Workout>().AsEnumerable();
        }

        // GET /api/workout/5
        public Workout Get(Guid id)
        {
            return _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);
        }

        // POST /api/workouts
        public HttpResponseMessage<Workout> Post(Workout workout)
        {
            var id = _unitOfWork.CurrentSession.Save(workout);
            _unitOfWork.Commit();

            var response = new HttpResponseMessage<Workout>
                (workout, HttpStatusCode.Created);
            response.Headers.Location = new Uri(Request.RequestUri,
                Url.Route(null, new { id }));

            return response;
        }

        // PUT /api/workouts/5
        public Workout Put(Guid id, Workout workout)
        {
            var existingWorkout = _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);

            if(existingWorkout==null)
                throw new HttpResponseException(HttpStatusCode.NotFound);

            _unitOfWork.CurrentSession.Update(workout);
            _unitOfWork.Commit();
        }

        // DELETE /api/workouts/5
        public HttpResponseMessage Delete(Guid id)
        {
            var existingWorkout = _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);

            if(existingWorkout==null)
                return new HttpResponseMessage(HttpStatusCode.NoContent);

            _unitOfWork.CurrentSession.Delete(existingWorkout);

            _unitOfWork.Commit();

            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
}



Happy Api creating.

No comments:

Post a Comment