Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject ServiceStack AuthSession into my repository classes?

Tags:

servicestack

I am struggling to find the correct way to inject the current instance of a UserAuthSession object (derived from ServiceStack's AuthUserSession) into my data-access repositories in order for them to automatically update change tracking fields on insert/update/delete operations.

If I were newing-up repositories in my service code it would be a no-brainer, I would just do:

var repo = new MyRepository(SessionAs<UserAuthSession>());

However, my repositories are auto-wired (injected) into the services, so the UserAuthSession has to be grabbed from somewhere in the lambda defined for the repository's registration with the IOC container, e.g.:

public class AppHost : AppHostBase
{
    public override void Configure(Container container)
    {
        container.Register<ICacheClient>(new MemoryCacheClient());
        container.Register<IRepository>(c =>
        {
            return new MyRepository(**?????**);  <-- resolve and pass UserAuthSession
        }
    }
}

Now, looking at the ServiceStack code for the Service class:

    private object userSession;
    protected virtual TUserSession SessionAs<TUserSession>()
    {
        if (userSession == null)
        {
            userSession = TryResolve<TUserSession>(); //Easier to mock
            if (userSession == null)
                userSession = Cache.SessionAs<TUserSession>(Request, Response);
        }
        return (TUserSession)userSession;
    }

I can see that it looks up the cached session based on the current Request and Response, but those are not available to me in the lambda.

What's the solution? Or am I approaching the problem from an entirely wrong angle?

like image 578
Caspian Canuck Avatar asked Jul 11 '13 18:07

Caspian Canuck


1 Answers

Found the answer in another StackOverflow post that stores the session built from the request in the request/thread-scoped Items dictionary of ServiceStack.Common.HostContext. .

My AppHost.Configure() now has the following code:

// Add a request filter storing the current session in HostContext to be
// accessible from anywhere within the scope of the current request.
RequestFilters.Add((httpReq, httpRes, requestDTO) =>
{
    var session = httpReq.GetSession();
    HostContext.Instance.Items.Add(Constants.UserSessionKey, session);
});

// Make UserAuthSession resolvable from HostContext.Instance.Items.
container.Register<UserAuthSession>(c =>
{
    return HostContext.Instance.Items[Constants.UserSessionKey] as UserAuthSession;
});

// Wire up the repository.
container.Register<IRepository>(c => 
{ 
    return new MyRepository(c.Resolve<UserAuthSession>()); 
});
like image 59
Caspian Canuck Avatar answered Dec 13 '22 07:12

Caspian Canuck