Friday, December 9, 2011

Aspect Oriented Programming and Interceptor pattern - Creating a Session handler for ASP.NET


Interceptor pattern can be used for addressing cross cutting concerns in the application that happens at either the beginning or end of a method. For e.g. checking the validity of the input parameters before executing the method and throwing exceptions, catching and logging exceptions etc. These situations can be encapsulated in a reusable component that can be processed by the compiler and produce executable code (AOP).
Unity allows developers to implement the idea of interception by allowing creation of objects that can add some extra code on the target method before or after the regular execution of these target methods. In this post, I'll show how to create a Session handler for ASP.Net using the interface interception mechanism provided by unity application block, that will allow you to address encapsulate the logic for checking session for a value before execution of the method and returning back the value from session if available. The same handler can be used to also add the return value to the session if not available so that this value can be retrieved next time.
Creating the session handler
public class SessionHandler : ICallHandler
{
    private readonly string _sessionKey;

    public SessionHandler(string sessionKey)
    {
        _sessionKey = sessionKey;
    }

    public ISessionService SessionService
    {
        get { return Container.Instance.Resolve<ISessionService>(); }
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        if (SessionService.Contains(_sessionKey))
        {
            input.CreateMethodReturn(SessionService.Get(_sessionKey));
            return getNext()(input, getNext);
        }

        var returnValue = getNext()(input, getNext);
        SessionService.Add(_sessionKey, returnValue.ReturnValue);
        return returnValue;
    }

    public int Order { get; set; }
}

The session handler uses the session service which encapsulates the actual Session object to add/ remove values from the session.  You can also use the HttpContext.Current.Session object here.
Creating the Attribute for the handler
public class SessionDependencyAttribute : HandlerAttribute
{
    private readonly string _sessionKey;
       
    public SessionDependencyAttribute(string sessionKey)
    {
        _sessionKey = sessionKey;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new SessionHandler(_sessionKey);
    }
}

Creating a service and using the SessionHandler we created.
public interface IMockService
{
    [SessionDependency("TestKey")]
    string GetValue(bool flag);
}

public class MockService : IMockService
{
    public string GetValue(bool flag)
    {
        return flag ? "True" : "False";
    }
}

Configuring the Unity container
_container = new UnityContainer();
_container.AddNewExtension<Interception>();


_container
    .RegisterType<ISessionService, SessionService>()
    .RegisterType<IMockService, MockService>()
    .RegisterType<MockPresenter>()
    .Configure<Interception>().SetDefaultInterceptorFor<IMockService>(new InterfaceInterceptor());

Test cases
[TestMethod]
public void MethodShouldReturnValueFromSessionIfValueDoesNotExistsAndAddToSession()
{
    var service = Container.Instance.Resolve<IMockService>();
    var actual = service.GetValue(true);

    Assert.IsTrue(SessionService.Contains("TestKey"));
}