从 ServiceReference 调用的响应中获取 Header 值 (Set-Cookie)

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

我正在处理一个项目,我必须在 SOAP Web 服务表单中调用 API 并获得响应。当响应返回时,我必须从 header 中提取一个 Set-Cookie 值,并在 header Cookie 值中传递后续 API 请求。最初,我一直在使用 XmlWriter 从头开始​​构建我的 SOAP 文档。我的一个队友让我开始使用服务参考,这意味着我不必编写任何自定义 XML(大赢)。

我的主要问题是我必须获得 header 值,否则 API 调用将无法工作。有没有办法在获得响应 header 的同时仍然能够使用服务引用及其附带的所有优点?

我一天中的大部分时间都在试图解决这个问题...我最终编写了一个 WCF 服务来模拟设置 cookie 并将其作为 OperationContract 的一部分发送出去(尽管这是不好的做法,我实际上不会做,因为 WCF 不仅仅是 HTTP)。

最初我认为 Message Inspectors 可以解决问题,但是 code-iteration 几个小时后我最终写了一个自定义 WebClient class 到 "simulate" 服务引用,这允许我在 CookieContainer 中看到 Headers。

所以在尝试了所有这些不同的想法并编写了一页又一页的代码之后,按照大多数时候我尝试了一些我以前没有做过的事情,我偶然发现了 google 中的一篇文章(在搜索一些东西时与原问题完全不同):

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

阅读部分(Ad-hoc cookie 管理),这是我的实现(使用我创建的测试服务来模拟您的问题)。您可能会做更多 sanity/error 检查 re-assemble 来自 header 字符串的 cookie 的部分...

        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);
                }
            }

        } 

所以我花了更多时间挖掘、搜索、摆弄 MessageBehaviors 和 web.config 设置,终于找到了解决我需要的东西。我将上面的答案标记为这个问题的答案,因为它与我解决问题的方式足够接近,但我认为我完成它的方式更清晰一些,并且与上面的答案完全不同,足以保证不仅仅是评论.

this MSDN article 开始,您可以使用 OperationContextScope 检查响应并向后续请求添加值。

我的代码最终看起来像这样:

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();
}