Jeffrey Sullivan - 438 - May 25, 2014

Is it possible to access session (and specifically, session via EndpointHost.AppHost.TryResolve<ICacheClient>().SessionAs<MyUserSession>(); inside of a service host based off of AppHostHttpListenerBase?

The error in the source implies that it’s only accessible via ASp.NET objects, which limits its usefulness for regression/functional testing via an in-proc host.

(More detailed version of this Q was posted on StackOverflow. See link.)

Jeffrey Sullivan:

Yeah, we had figured all of that out, but our solution (i.e., a SetSession(MyUserSession session) method call on the model before each service invocation) seems rather inelegant, and I was wondering if there were any best practices around it that people have come up with.  I didn’t find any when searching, but this seems like a solved problem.

Whenever I need access to the session I just pass it in as an argument to whichever dependency needs it. You can reduce any boilerplate with a base class or an extension method. 

Kyle Gobel:

I posted what I do for this sorta thing on your question, not sure if it’s bad or good…but works for me.

Yeah, retrieving the session is basically just resolving the UserSession stored in the cache at the SessionId which is derived from the ss-id/ss-pid Cookies sent with the request.

The SessionAs&lt;T&gt; API provides optional overloads so you can pass in the HttpListener Request/Response, see:

https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/SessionExtensions.cs#L177

If a Request/Response isn’t provided it falls back to using ASP.NET’s HttpContext.Current. 

You can also manually get the SessionId from the request with httpReq.GetSessionId() ext method:
https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/SessionExtensions.cs#L21

Which would look like:

var sessionId = httpReq.GetSessionId();
var sessionKey = IdUtils.CreateUrn<IAuthSession>(sessionId);
var session = Cache.Get<TUserSession>(sessionKey);

Jeffrey Sullivan:

Okay, thanks Demis.

This works fine for services, but for Models which want to access the permissions data held in the session post-authentication, we end up needing to manually wire the Session into the Model for each call, even though the model is auto-wired into its service by Funq. (Because the httpRequest can’t be auto-wired to the Model as far as I can tell.)

Is there a best practice for exposing the current user session to model classes in a clean and DRY manner?

The Session is not a normal IOC dependency, it requires access to the current Request Cookies to work out the sessionKey at where the UserSession is stored (as shown in the code above). 

It’s not injectable, you need the current request at runtime, the cache to resolve it and the generic type of the TUserSession to deserialize it into, i.e. what the Cache.SessionAs<T>(Request,Response) API requires. 

Jeffrey Sullivan:

Kyle, that’s an interesting approach, and I suppose my questions are twofold: 1) is that concurrency-safe? 2) What is the performance impact of running a Resolve() for each session access? (Certainly one could pair this with a singleton pattern to do the resolve only once per call lifecycle)?