1
votes

I am using MVC 3, I have a range of Controllers depending on various repositories, 1 of my repository relies on the http context session. I have created interfaces for each of my repositories in order to use the Windsor-Castle IoC.

How can I pass the current session object down to the repository that needs it?

I used to be able to do this and the "Resolve" would take care passing the session to the repository that needed it, somehow I cannot do this in the latest version (2.5.3 Feb 2011):

Protected Overrides Function GetControllerInstance(ByVal requestContext As System.Web.Routing.RequestContext, _
                                                   ByVal controllerType As System.Type) As System.Web.Mvc.IController
    Dim match As IController
    ' 1 or more components may need the session,
    ' adding it as a (possible) dependency
    Dim deps As New Hashtable
    deps.Add("session", HttpContext.Current.Session)
    match = container.Resolve(controllerType, deps)
    Return match
End Function

Thanks, Vincent

2

2 Answers

4
votes

Look closely at your design. When you look at it functionaly, your repository doesn't really depend on the the session at all, but at some data you store in the session. Create an abstraction over the things you want to extract from the session and let the repository depend on such abstraction. For instance:

public interface IUserProvider
{
    int GetCurrentUserId();
}

public class SomeRepository : ISomeRepository
{
    private readonly IUserProvider userProvider;

    public SomeRepository(IUserProvider userProvider)
    {
        this.userProvider = userProvider;
    }
}

Now you can create the following implementation of that abstraction:

private class HttpSessionUserProvider : IUserProvider
{
    public int GetCurrentUserId()
    {
        return (int)HttpContext.Current.Session["UserId"];
    }
}

You can register this concrete type in your IoC configuration.

This is much better, because you don't want to let your repository depend directly on the HTTP session. This makes testing harder and creates a dependency between your repository and a specific presentation technology.

2
votes

The controller factory's sole responsibility is to create controllers. Not handling sessions or any other dependencies. It's best to just register the session as a separate component and let Windsor autowire it. Remove the 'deps' Hashtable from there and register:

  container.Register(Component.For<HttpSessionStateBase>()
      .LifeStyle.PerWebRequest
      .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)));

Then inject HttpSessionStateBase in your controller.

BTW: controllers already have access to the session, there is no need to do this if you're just injecting the session to controllers.