0

I'm using ServiceStack 3.9.71. I'm going into the self-hosted route to be able to deploy on Linux and still be able to avoid the memory leak issues plaguing Mono.

The thing with self-hosted service is we no longer have the request. Without it, we don't have session as well. Attempts to get the session will fail with

Only ASP.NET Requests accessible via Singletons are supported

due to null request object.

Questions are:

  1. Can someone explain why can't we have the request in the self-hosted ServiceStack service?
  2. How do we get around it?

For example, if the service needs to know the details of the user (e.g what we would have in ICustomAuthSession) who invoked the request, how do we do that? I can see that the Cache actually contains the session, but since we don't have the request then there's no SessionKey that we can use to grab the session from the Cache. I somewhat see some discussion on it, but can't quite make out what to do exactly.

4

1 回答 1

1

Self-hosted ServiceStack applications do have access to the Request and Sessions in the same way that ServiceStack IIS applications do.

Accessing the Request

Self-hosted applications use the HttpListenerRequest class to handle the HTTP requests, but ServiceStack abstracts this away into an IHttpRequest, which provides a consistent way to access the HTTP request data, between either IIS or self-hosted applications.

If you are in a ServiceStack Service, then you can access the IHttpRequest through the base.Request object. See ServiceBase.cs for the methods provided by the base of Service.

public class MyService : Service
{
    // Your action method
    public object Get(MyRequest request)
    {
        // Access to the request
        var request = base.Request;
    }
}

Or the request object is provided to you during the request filters:

this.RequestFilters.Add((httpReq, httpResp, requestDto) => {

    // Access to the request through httpReq 

});

It's rare that you should need access to the original underlying request, as the abstraction provided by IHttpRequest should cover you in most cases. But if you wanted, for example to access the requests client certificate you can get this from the underlying request. You can do this by casting the IHttpRequest.OriginalRequest:

var originalRequest = IHttpRequest.OriginalRequest as HttpListenerRequest;
if(originalRequest != null)
{
    // Example of accessing the client certificate
    var certificate = originalRequest.GetClientCertificate();
}   

Accessing the Session

It sounds like you aren't accessing the session correctly. If you are using ServiceStack's SessionFeature, which is used by the AuthenticationFeature then you don't have to worry about retrieving the SessionId and then looking up values from the cache client, ServiceStack has built in methods for handling accessing the session.

There are different ways to access the session depending on whether you are using ServiceStack's authentication which provides it own user session mechanism, or whether you are using the simple key value storage analogous to the standard ASP.NET key value session store. You can learn more about sessions here.

The simple cache backed Key Value store (Untyped session bag):

public class MyService : Service
{
    public object Get(MyRequest request)
    {
        // Set
        Session.Set<int>("Age",123);

        // Retrieve
        var age = Session.Get<int>("Age");        
    }
}

Using the session provided by ServiceStack's Authentication Feature i.e. IAuthSession:

public class MyService : Service
{
    public object Get(MyRequest request)
    {
        // Provides access to the IAuthSession user session (if you are using the authentication feature)
        var session = base.GetSession();
        session.FirstName = "John";
    }
}

Using a custom session type with ServiceStack's Authentication Feature (which appears to be what you are trying to do).

public class MyService : Service
{
    public object Get(MyRequest request)
    {
        var mySession = SessionAs<MySession>();
        mySession.FirstName = "Clark";
        mySession.LastName = "Kent";
        mySession.SuperheroIdentity = "Superman";
    }
}

public class MySession : AuthUserSession
{
    public string SuperheroIdentity { get; set; }
}

I hope this helps.

于 2014-07-31T09:22:33.860 回答