dst3p
dst3p

Reputation: 1038

Get Header Value (Set-Cookie) out of Response from a ServiceReference Call

I'm working on a project where I have to call an API in SOAP web service form and get a response back. When the response comes back, there is a Set-Cookie value I have to pull from the header and pass along in the header Cookie value with subsequent API requests. Initially, I've been building my SOAP document from scratch using XmlWriter. A teammate of mine turned me on to using a Service Reference which meant that I didn't have to write any of the custom XML (BIG WIN).

My main problem is that I have to get the header value, without that, the API calls won't work. Is there a way to get the response header while still being able to use a Service Reference and all the goodness that comes with it?

Upvotes: 3

Views: 5508

Answers (2)

dst3p
dst3p

Reputation: 1038

So I spent some more time digging, searching, messing around with MessageBehaviors and web.config settings, and finally found something that solved what I needed. I marked the answer above as the answer to this question because it's close enough to how i solved my issue, but I think the way I've done it is a bit cleaner and is different enough from the above answer to warrant more than a comment.

From this MSDN article, you can use the OperationContextScope to inspect the response and add values to the subsequent request.

My code ended up looking like this:

string sharedCookie = string.Empty;

using (MyClient client = new MyClient())
{
    client.RequestThatContainsCookieValue();

    // This gets the response context
    HttpResponseMessageProperty response = (HttpResponseMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];

    sharedCookie = response.Headers["Set-Cookie"];

    // Create a new request property
    HttpRequestMessageProperty request = new HttpRequestMessageProperty();

    // And add the cookie to the Header
    request.Headers["Cookie"] = sharedCookie;

    // Add the new request properties to the outgoing message
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = request;

    var response = client.ThisCallPassesTheCookieInTheHeader();
}

Upvotes: 1

OBR_EXO
OBR_EXO

Reputation: 600

I spent most of the day trying to figure this one out... I ended up writing a WCF service to simulate setting a cookie and sending it out as part of an OperationContract (although this is bad practice, something I wouldn't do practically as WCF isn't HTTP only).

Initially I thought Message Inspectors would do the trick, however after a few hours of code-iteration I ended up writing a custom WebClient class to "simulate" the service reference, which allowed me to see the Headers in a CookieContainer.

So after trying all these different ideas and writing pages and pages of code, as per most times I try something I haven't done before, I stumbled across an article in google (whilst searching for something completely different to the original problem):

http://megakemp.com/2009/02/06/managing-shared-cookies-in-wcf/

Read the section (Ad-hoc cookie management), here's my implementation (using the test Service I created to simulate your problem). You could probably do more sanity/error checking on the section where I re-assemble the cookies from the header string...

        List<string> strings = null;

        // Using Custom Bindings to allow Fiddler to see the HTTP interchange.
        BasicHttpBinding binding = new BasicHttpBinding();            
        binding.AllowCookies = true;
        binding.BypassProxyOnLocal = false;
        binding.ProxyAddress = new Uri("http://127.0.0.1:8888");
        binding.UseDefaultWebProxy = false;

        EndpointAddress url = new EndpointAddress("http://192.168.20.4:42312/Classes/TestService.svc");

        using (TestServiceClient client = new TestServiceClient(binding,url))
        {                
            using (new OperationContextScope(client.InnerChannel))
            {
                strings = new List<string>(client.WSResult());
                HttpResponseMessageProperty response = (HttpResponseMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];

                CookieCollection cookies = new CookieCollection();
                foreach (string str in response.Headers["Set-Cookie"].ToString().Split(";".ToCharArray()))
                {
                    Cookie cookie = new Cookie(str.Split("=".ToCharArray())[0].Trim(), str.Split("=".ToCharArray())[1].Trim());
                    cookies.Add(cookie);
                }
            }

        } 

Upvotes: 1

Related Questions