Home
Gallery
GuestBook
SourceCode
Contact

MPBlog Implementation. Part 5

Posted in .NET
This post has been read 8864 times

Setting up StructureMap and The Unit Of Work ActionFilter

UnitOfWork ActionFilter

In my previous post I had created the repository implementations along with unit of work. But how do we use this unit of work in our application. ASP.NET MVC has a concept of ActionFilters. These could be applied to an action or a controller in general. The two main methods that concern us are OnActionExecuting and the OnActionExecuted. As seen in the code below we call the initialize method of the unit of work which would create a new transaction for us and this is held until the action is complete after which we commit the transaction. We are getting a new instance of _unitOfWork through an IoC container which I will talk about in a bit.

namespace MPBlog.Web.UI.ActionFilters

{

    using System;

    using System.Web.Mvc;

    using Core.BaseClasses;

    using StructureMap;

 

    public class UseUnitOfWOrkAttribute : ActionFilterAttribute

    {

        private readonly IUnitOfWork _unitOfWork;

 

        public UseUnitOfWOrkAttribute()

        {

            _unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();

        }

 

        public UseUnitOfWOrkAttribute( IUnitOfWork unitOfWork )

        {

            _unitOfWork = unitOfWork;

        }

 

        public override void OnActionExecuting( ActionExecutingContext filterContext )

        {

            _unitOfWork.Initialize();

        }

 

        public override void OnActionExecuted( ActionExecutedContext filterContext )

        {

            try

            {

                _unitOfWork.Commit();

            }

            catch( Exception )

            {

                _unitOfWork.Rollback();

                throw;

            }

            finally

            {

                _unitOfWork.Dispose();

            }

        }

    }

}

We use this action filter either by decoration individual action with the attribute or if we want all actions to use the unit of work, then we can decorate the class itself with the attribute. In the following code I am using the UseUnitOfWork filter on the Index action.

namespace MPBlog.Web.UI.Controllers

{

    using System.Web.Mvc;

    using ActionFilters;

    using Core.Services;

 

    [HandleError]

    public class HomeController : Controller

    {

        private readonly IBlogService _blogService;

 

        public HomeController(IBlogService blogService)

        {

            _blogService = blogService;

        }

 

        [UseUnitOfWOrk]

        public ActionResult Index()

        {

            var posts = _blogService.GetAllPosts();

            return View(posts);

        }

    }

}

Attributes may look a bit intrusive (atleast for me). I like how FubuMVC handles this. In FubuMVC, we have something called behaviors and this can be configured in the application start. So if we want all our actions to use the unit of work, then we can set the behavior as shown below and that's it, no more attributes on the action or controller. In the following code the access_the_database_through_a_unit_of_work has the same implementation as the filter we created.

ControllerConfig.Configure = x =>

{

    // Default Behaviors for all actions -- ordered as they're executed

    /////////////////////////////////////////////////

    x.ByDefault.EveryControllerAction(d => d

        .Will<access_the_database_through_a_unit_of_work>()

        );

};

Services

Instead of accessing the repository directly from the controllers, I have created a separate service which delegates the work to the repository to the operations related. Following is an example of a blog service. I have kept the methods to be minimal for brevity.

namespace MPBlog.Core.Services

{

    using System.Collections.Generic;

    using Domain;

 

    public interface IBlogService

    {

        IEnumerable<Post> GetAllPosts();

        IEnumerable<Post> GetPostsByTag(string tag);

        Post GetPostById( int postID );

        Post GetPostBySlug( string slug );

 

        void SavePost( Post post );

        void UpdatePost( Post post );

        void DeletePost( Post post );

    }

}

namespace MPBlog.Core.Services

{

    using System.Collections.Generic;

    using System.Linq;

    using BaseClasses;

    using Domain;

 

    public class BlogService : IBlogService

    {

        private readonly IRepository _repository;

 

        public BlogService( IRepository repository )

        {

            _repository = repository;

        }

 

        public IEnumerable<Post> GetAllPosts()

        {

            return _repository.Query<Post>().AsEnumerable();

        }

 

        public IEnumerable<Post> GetPostsByTag( string tag )

        {

            return

                _repository.Query<Tag>( t => t.Description.Equals( tag ) ).

                    SingleOrDefault().Posts;

        }

 

        public Post GetPostById( int postId )

        {

            return _repository.Load<Post>( postId );

        }

 

        public Post GetPostBySlug( string slug )

        {

            return _repository.Query<Post>( p => p.PostSlug.Equals( slug ) ).SingleOrDefault();

        }

 

        public void SavePost( Post post )

        {

            _repository.Save( post );

        }

 

        public void UpdatePost( Post post )

        {

            _repository.Save( post );

        }

 

        public void DeletePost( Post post )

        {

            _repository.Delete( post );

        }

    }

}

Dependency Injection using StructureMap

If we look at the all the code that has been shown till now, we see that, there is almost always an interface declared and we can nowhere see a direct instantiation of the object that is required. So how do we get a new instance of an object. This is where an Inversion Of Control (IoC/DI)  container comes into play. Basically what it does is to give you a concrete objects whenever we require.

I have used constructor injection where ever possible. How it works is, by defining our own ControllerFactory and create the controller ourselves instead of ASP.NET MVC doing it for us. In the below code I have a StrucutreMapControllerFactory from where I am getting an instance of the controller. This factory inherits from the DefaultControllerFactory for ASP.NET MVC and we override the controller building method.

namespace MPBlog.Web.UI.Controllers

{

    using System;

    using System.Web.Mvc;

    using StructureMap;

 

    public class StructureMapControllerFactory : DefaultControllerFactory

    {

        protected override IController GetControllerInstance(Type controllerType)

        {

            IController result = null;

            if (controllerType != null)

            {

                try

                {

                    result = ObjectFactory.GetInstance(controllerType) as Controller;

 

                }

                catch (StructureMapException)

                {

                    System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());

                    throw;

                }

            }

            return result;

        }

    }

}

We set this controller factory in our Application_Start method in the global.asax file like so.

RegisterRoutes( RouteTable.Routes );

Bootstrapper.Bootstrap();

ControllerBuilder.Current.SetControllerFactory(

    new StructureMapControllerFactory());

Now that we have controllerfactory ready, we can configure our dependencies. The way to configure our dependency is through a registry which provides a fluent interface. The following code shows all the dependencies being loaded into the container through the MPBlogRegistry. 

namespace MPBlog.Web.UI

{

    using StructureMap;

 

    public class Bootstrapper : IBootstrapper

    {

        public void BootstrapStructureMap()

        {

            ObjectFactory.Initialize( x => x.AddRegistry( new MPBlogRegistry() ));

        }

 

        public static void Bootstrap()

        {

            new Bootstrapper().BootstrapStructureMap();

        }

    }

}

using System.Configuration;

 

namespace MPBlog.Web.UI

{

    using Core.BaseClasses;

    using Core.Services;

    using FluentNHibernate;

    using Persistence;

    using Persistence.Config;

    using Persistence.RepositoryImpl;

    using Persistence.UnitOfWork;

    using StructureMap.Attributes;

    using StructureMap.Configuration.DSL;

 

    public class MPBlogRegistry : Registry

    {

        public MPBlogRegistry()

        {

            ForRequestedType<ISessionSource>().AsSingletons()

                .TheDefault.Is.ConstructedBy( context =>

                    context.GetInstance<ISessionSourceConfiguration>()

                    .CreateSessionSource( new MPBlogPersistenceModel() ) );

 

            ForRequestedType<ISessionSourceConfiguration>().AsSingletons()

                .TheDefault.Is.OfConcreteType<SQLSessionSourceConfiguration>()

                .WithCtorArg( "connectionString" )

                    .EqualTo( ConfigurationManager.ConnectionStrings["MPBlog"].ConnectionString )

                .WithCtorArg( "resetDb" )

                    .EqualToAppSetting( "reset" );

 

            ForRequestedType<IUnitOfWork>()

                .TheDefault.Is.ConstructedBy( context => context.GetInstance<INHibernateUnitOfWork>() );

 

            ForRequestedType<INHibernateUnitOfWork>().CacheBy( InstanceScope.Hybrid )

                .TheDefault.Is.OfConcreteType<NHibernateUnitOfWork>();

 

            ForRequestedType<IRepository>().AsSingletons()

                .TheDefault.Is.OfConcreteType<NHRepository>();

 

            ForRequestedType<IBlogService>().AsSingletons()

                .TheDefault.Is.OfConcreteType<BlogService>();

        }

    }

}

Once this is done whenever we ask for a instance of an object, the IoC toll will lookup and give us the concerned concrete object.

Thats it for now.




Comment posted on Thursday, June 25, 2009 9:11 AM
In the service example does the repository use the Unit of Work?? How is the lifetime managed?
Comment posted on Thursday, June 25, 2009 9:19 AM
@Adam,

Yes it does, the repository itself is injected with a unit of work. This can be seen in my previous post. We have one unit of work per controller action, which will be disposed once the action completes
Comment posted on Tuesday, June 30, 2009 10:35 AM
The UnitOfWork action filter is interesting and definitely MVCish but why not use NHibernate.Burrow to automatically manage your sessions? Applying the attribute to every Action seems like an unnecessary overhead to me.

Also, I see that you chose to expose only the services layer to your controllers which forces the services to sort of repeat what the repository layer already does. Wouldn't it be better to just expose the repository layer to the controllers directly? I can understand if you'd need to perform some business logic in the services but I find in most cases, they can be easily moved to the domain layer keeping up with the spirit of DDD and Naked Objects Pattern. Obviously, theres nothing wrong with *only* exposing the services layer, it just seems uneccessary to me.

I would love to hear your thoughts on this.
Comment posted on Tuesday, June 30, 2009 11:15 AM
@Rahul,

I have not tried Burrow until now. Will have a look at it though. I mentioned that action filters are a bit intrusive and fubumvc does a good job at handling this through behaviors. Maarten Balliauw has blogged about a similar thing in asp.net mvc.

And you are right about repositories being exposed to the controller. But personally for me, I wouldn't want the querying part being exposed directly to the controller. I would rather have a service do the querying which is what i have done in the example.

Thoughts on this?
Comment posted on Wednesday, July 01, 2009 12:09 AM
The services layer encapsulating the repository is certainly not a bad design. I try to be a purist as much as I can. I beleive the services layer should only contain logic that simply can't fit anywhere else like AuthenticationService, MembershipService, CryptographicService, etc. An individual entity cannot handle authentication by itself and a repository cannot do it either (as it would give a whole new meaning to it), this easily warrants the need for an AuthenticationService.

I would understand if you exposed a repository with a method that invites an open query, thats just inviting trouble but a repository that neatly wraps around all the queries and exposes them via properly named methods is a good design and can be exposed to the higher levels imo.

Usually, I see people encapsulating the repository layer with services because they handle their validation, etc in the services layer. I strongly beleive validation belong to the entities themselves. The repository base can call a common Validate() method for all entities in its Save/Update() method which in turn reduces the services to nothing more than plain vanilla CRUD wrappers and its the duty of the repository layer to handle CRUD, not the services layer.

Again, this is just the way I like to do things and I definitely don't consider this as "best practise".
Comment posted on Wednesday, July 01, 2009 7:03 PM
@Rahul,

Do you mean to say instead of the repository exposing the query method, I should expose methods that inturn does the querying.

And validation, I have not yet gone into that. I was planning to do in my next post though.
Comment posted on Wednesday, August 19, 2009 1:32 AM
I think a services layer is very useful for many reasons. For complicated apps you will often be doing far more than just persisting an object to the db. You might be emailing someone, saving a document, providing validation and so on. You may also chose to use the services layer to provide view specific objects (DTOs) to your client app and the web app can remain ignorant of the domain completely. It allows your repository or persistence layer to stick to it's job and keep overly complicated code from the client.
Comment posted on Thursday, June 14, 2012 7:49 AM
Interesting post. Internet is the best place where you can gather information about the poor credit card offers.When a person searches on the Internet with the keywords “zero fee bad credit cards”,then he will get a thousand of results about the companies which come with such offering.
Comment posted on Thursday, July 26, 2012 9:21 PM
very intresting For Jobs In Your City Visit our site bharatdesi.com
Comment posted on Tuesday, August 21, 2012 11:43 PM
Nice blog having having useful information. Keep this sort of valuable work in future. I will be back after some time
Name:
E-mail:
Website:
Comment:
 
Anti Bot Image:

Insert Cancel


Subscribe

Random Photo

My Tweets


Top Posts

Source Code

The source code to this site is open-source. You can download the code from here.

Categories


Recent Blogs


Archives


Blogroll