从 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);
}
}
}
所以我花了更多时间挖掘、搜索、摆弄 MessageBehavior
s 和 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();
}
我正在处理一个项目,我必须在 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);
}
}
}
所以我花了更多时间挖掘、搜索、摆弄 MessageBehavior
s 和 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();
}