Answered by:
How to support the ASP.NET session in WCF calls?

Question
-
User-506274534 posted
Hi there
The question is answered, probably, here:
https://blogs.msdn.microsoft.com/wenlong/2010/02/20/using-asp-net-sessions-from-wcf/
but that code is all around the OperationContext.Current, which is not NULL only for a given code example.
In my case the system creates all proxies automatically and all I do is calling things like:
LoginServiceReference.LoginClient wc = new LoginServiceReference.LoginClient(); LoginServiceReference.IDTWebUserDTO user = wc.DoLogin(model.Login, model.Password);
It works Ok, but as you may see, the LoginClient is created for me automatically. When calling wc.DoLogin there is no way to get into its context to obtain the OperationContext. For sure, I can modify the generated proxy, but next time the system will re-generate it. Bad approach.
For me the OperationContext.Current is always NULL here. How to get the ASP.NET session ID (as the blogger does in his InitialInvoke() method) and how to assign it (as in his Invoke2() method) ?
Maybe you can suggest other technics to maintain the ASP.NET session for WCF communication?
Thanks.
Friday, September 15, 2017 9:07 PM
Answers
-
User1168443798 posted
Hi Nick,
For OperationContext in the link, it is a context in OperationContextScope. You could create a OperationContextScope from client.InnerChannel.
Here is a simple code
void InitialInvoke() { WCFSessionSvc.HelloServiceClient client = new WCFSessionSvc.HelloServiceClient(); using (new OperationContextScope((IContextChannel)client.InnerChannel)) { MessageBox.Show(client.Greet("Hello")); HttpResponseMessageProperty responseProperty = OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; helper = HttpSessionCookieHelper.Create((string)responseProperty.Headers[HttpResponseHeader.SetCookie]); } } void Invoke2() { WCFSessionSvc.HelloServiceClient client = new WCFSessionSvc.HelloServiceClient(); using (new OperationContextScope((IContextChannel)client.InnerChannel)) { HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); helper.AddSessionIdToRequest(requestProperty); OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; MessageBox.Show(client.Greet("Howdy")); } }
You could replace WCFSessionSvc.HelloServiceClient with your own WCF generated Client object like LoginServiceReference.LoginClient.
Best Regards,
Edward
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, September 18, 2017 3:04 AM
All replies
-
User1120430333 posted
What is the purpose of the session used by client and service?
Saturday, September 16, 2017 3:02 PM -
User-506274534 posted
Hi there
You have an easy answer: it is the AP.NET session and its purpose is to make a WEB s/w statefull.
Sunday, September 17, 2017 12:34 PM -
User1120430333 posted
I guess I should have asked what are you trying to keep in session between the WCF client and service? An object? Objects? Complex Object? Complex Objects? Object graph?
Sunday, September 17, 2017 1:46 PM -
User-506274534 posted
Yes, all of you listed. One note: I have not been talking about a "session between the WCF client and service". Session lives on the server side only and being used by the IIS-hosted WCF service. I need to make sure that the next sequential call to WCF function on the client is invoked in the server's context which has the same ASP.NET session. This is what my initial question about. How to accomplish that?
Thanks.
Sunday, September 17, 2017 3:48 PM -
User1120430333 posted
Yes, all of you listed. One note: I have not been talking about a "session between the WCF client and service". Session lives on the server side only and being used by the IIS-hosted WCF service. I need to make sure that the next sequential call to WCF function on the client is invoked in the server's context which has the same ASP.NET session. This is what my initial question about. How to accomplish that?
Thanks.
Well, you could use a class/container with the container holding objects in it putting the container into session holding the objects. On the return to the client, the service takes the container with all the objects in it, XML serializes it and writes it to a database table. The client makes the call to the service, the WCF service reads the container of XML objects XML from the table, deserialize the XML back into objects and puts the container of objects back into session on the service side.
The service could use a GUID, timestamp and possible user-id as the key for the table record when the container is persisted, sending the key to the client and the client keeping this information in state. The client sends the key back to the service, it takes the key, reads the XML from the table and puts the container back into session.
It maybe that the client initiates the key sending it to the service. You would have to periodically clean-up the table and delete old records.
You could use the DTO pattern with DTO(s) kept in the container.
https://www.codeproject.com/Articles/8824/C-Data-Transfer-Object
Sunday, September 17, 2017 9:30 PM -
User1168443798 posted
Hi Nick,
For OperationContext in the link, it is a context in OperationContextScope. You could create a OperationContextScope from client.InnerChannel.
Here is a simple code
void InitialInvoke() { WCFSessionSvc.HelloServiceClient client = new WCFSessionSvc.HelloServiceClient(); using (new OperationContextScope((IContextChannel)client.InnerChannel)) { MessageBox.Show(client.Greet("Hello")); HttpResponseMessageProperty responseProperty = OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; helper = HttpSessionCookieHelper.Create((string)responseProperty.Headers[HttpResponseHeader.SetCookie]); } } void Invoke2() { WCFSessionSvc.HelloServiceClient client = new WCFSessionSvc.HelloServiceClient(); using (new OperationContextScope((IContextChannel)client.InnerChannel)) { HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); helper.AddSessionIdToRequest(requestProperty); OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; MessageBox.Show(client.Greet("Howdy")); } }
You could replace WCFSessionSvc.HelloServiceClient with your own WCF generated Client object like LoginServiceReference.LoginClient.
Best Regards,
Edward
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, September 18, 2017 3:04 AM -
User-506274534 posted
Hi Edward
This creating Context from the client's inner channel works fine. This is a viable solution.
A couple of questions more:
1. For the Silverlight application, why we never even thought of supporting the ASP.NET SessionId? Why it worked automatically?
2. Why it is not enough just to add the SessionId to the request header manually? If I do that, I see the IIS creates new SessionId and ignores what I passed in the header "ASP.NET_SessionId=..." for the WCF service
Thanks.
Monday, September 18, 2017 3:30 PM -
User1168443798 posted
Hi Nick,
For new issues, I would suggest you post new threads.
>> For the Silverlight application, why we never even thought of supporting the ASP.NET SessionId? Why it worked automatically?
For this issue, it is related with Silverlight, and you could consider posting in Silverlight forum.
Best Regards,
Edward
Tuesday, September 19, 2017 8:10 AM -
User1120430333 posted
The solution I proposed works no different as if MS SQL Server is setup to be the ASP.NET State Server where session objects are kept in state at the DB level.
Tuesday, September 19, 2017 12:05 PM