This is not a new topic. But interestingly I could not find a good example on the web while I wanted to find one for some other investigation. So I decided to create a sample here to show the following scenario:
Here I will show a simple example on how to achieve this.
WCF sessions are very different from ASP.NET Sessions. In short,
You can find more details for the comparisons of the two from the MSDN article “Using Sessions”.
While these two concepts are quite different and the usages are also drastically different, the WCF sample “HttpCookieSession” tried to use the similar idea as cookie-based ASP.NET sessions to provide WCF session support. The sample is a little bit complex and it does not use real ASP.NET sessions though.
There are many samples on how to use WCF sessions, for example, “How to: Create a Service That Requires Sessions” is a good one.
So I will only show how to use ASP.NET sessions from WCF below. It uses PerCall service to handle this. So different service instances have access to the same ASP.NET session state.
It is known that ASP.NET session states can be stored in different places: 1) In-Memory (thus In-process), 2) Out-of-proc state service, 3) SQL server, 4) a custom session-state store provider, etc. More details can be found in “ASP.NET Session State Overview”.
For simplicity, I will just show the in-memory case. Here is a very simple session state:
class MySessionState
{
int counter;
public MySessionState() {}
public int Counter { get { return this.counter; } }
public int Touch() { return Interlocked.Increment(ref this.counter); }
}
The state just contains a single counter. This state is stored in the session object as following:
MySessionState state = (MySessionState)HttpContext.Current.Session["MySessionState"];
if (state == null) {
state = new MySessionState();
HttpContext.Current.Session["MySessionState"] = state;
}
When the service receives a request, the sample increments the counter to demonstrate the sharing effect:
int counter = state.Touch();
It is very straightforward to enable the ASP.NET session states. You only need to run WCF service in the ASP.NET Compatibility mode as being specified in the web.config:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
Once the session states are enabled and there is session data populated as above, we can retrieve the Session Id from the cookie on the client side:
using (new OperationContextScope((IContextChannel)proxy))
{
Console.WriteLine(proxy.Greet("Hello"));
HttpResponseMessageProperty responseProperty =OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name]
as HttpResponseMessageProperty;
helper =HttpSessionCookieHelper.Create((string)responseProperty.Headers[HttpResponseHeader.SetCookie]);
}
Here the type “HttpSessionCookieHelper” is just a helper class that is used to retrieve the ASP.NET Session Id from the cookie string (with the cookie name “ASP.NET_SessionId”) and append the Session Id to the request. It is defined as following:
class HttpSessionCookieHelper
{
const string AspNetSessionIdCookieName = "ASP.NET_SessionId";
string aspNetSessionId;
public static HttpSessionCookieHelper Create(string cookieString);
public static HttpSessionCookieHelper CreateFromSessionId(string sessionId);
public void AddSessionIdToRequest(HttpRequestMessageProperty requestProperty);
public string AspNetSessionId { get { return this.aspNetSessionId; }
}
Once we get the Session Id retrieved from the response of the first request, we can share it for the subsequent client calls. Here is the example:
using (new OperationContextScope((IContextChannel)proxy))
{
HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty();
helper.AddSessionIdToRequest(requestProperty);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty;
Console.WriteLine(proxy.Greet("Howdy"));
}
The implementation of the HttpSessionCookieHelper.AddSessionIdToRequest does nothing but the following:
requestProperty.Headers[HttpRequestHeader.Cookie] = string.Format("{0}={1}", AspNetSessionIdCookieName, this.aspNetSessionId);
http://blogs.msdn.com/b/wenlong/archive/2010/02/21/using-asp-net-sessions-from-wcf.aspx
With this logic, the second request would share the same ASP.NET Session State on the server side.
Here are the steps on how to use it:
1) Unzip the attachment locally.
2) Create a virtual application with name “WCFAspNetSession” and the physical path points to the “WCFAspNetSession” directory.
3) Compile the client code and run it.
Here is the output of the sample:
[Session '1vgfq255e1lpe255whwprf55'] You said: Hello (counter: 1)
[Session '1vgfq255e1lpe255whwprf55'] You said: Howdy (counter: 2)
As you can see, the Session Ids for the two requests are the same and the counter for the shared state has increased.