我在哪里设置服务引用上的 CookieContainer?
Posted
技术标签:
【中文标题】我在哪里设置服务引用上的 CookieContainer?【英文标题】:Where do I set the CookieContainer on a Service Reference? 【发布时间】:2013-08-27 00:51:45 【问题描述】:例如,在 .NET 2.0 项目中将 WebService 引用添加到 ASMX 服务时,
var objService = new NameSpace.groupservices();
存在,
objService.CookieContainer = new System.Net.CookieContainer();
例如,将 ServiceReference 添加到 .NET 4.0 项目上的 ASMX 服务时,
var objService = new NameSpace.groupservicesSoapClient();
objService 没有任何 CookieContainer 属性
here 提出了类似的问题,但没有得到肯定的解决方案。
有人可以指导在哪里找到房产吗?
【问题讨论】:
@marc_s:即使是 ASMX 服务,他也应该使用“添加服务引用”。 【参考方案1】:与绑定到 HTTP 传输的 ASMX Web 服务相比,WCF 允许使用各种传输协议。因此,并非所有特定于协议的选项(例如用于 HTTP 传输的 Cookie)都在 WCF 服务参考中可用。
但是,您可以添加一个消息检查器来检查客户端和服务器之间发送的消息。 article 描述了一种将 cookie 发送到服务器的方法。
我已扩展示例以使用 CookieContainer。此外,以下代码显示了如何评估服务器发送的 Set-Cookie
标头以将新 cookie 添加到容器中。请注意,该示例显示了基本轮廓,但可能需要扩展或更多验证。但是,在一个简单的场景中它起作用了。
下面的 sn-p 显示了一个 WCF 服务的测试方法,该服务托管在 IIS 上并集成在 ASP.NET 框架中。它基本上以字符串形式回显发送到服务器的 cookie,并添加两个新的:
public string GetData(int value)
var reply = string.Join(", ",
from x in HttpContext.Current.Request.Cookies.AllKeys
select x + "=" + HttpContext.Current.Request.Cookies[x].Value);
HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test", "Test123"));
HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test2", "Test1234"));
return reply;
以下测试程序为 cookie 创建一个 CookieContainer,添加一个演示 cookie 并为服务的端点注册一个新行为:
class Program
static void Main(string[] args)
var cookieCont = new CookieContainer();
using(var svc = new TestServiceReference.TestServiceClient())
cookieCont.Add(svc.Endpoint.Address.Uri, new Cookie("TestClientCookie", "Cookie Value 123"));
var behave = new CookieBehavior(cookieCont);
svc.Endpoint.EndpointBehaviors.Add(behave);
var data = svc.GetData(123);
Console.WriteLine(data);
Console.WriteLine("---");
foreach (Cookie x in cookieCont.GetCookies(svc.Endpoint.Address.Uri))
Console.WriteLine(x.Name + "=" + x.Value);
Console.ReadLine();
该行为的目的是添加自定义消息检查器并移交 CookieContainer:
public class CookieBehavior : IEndpointBehavior
private CookieContainer cookieCont;
public CookieBehavior(CookieContainer cookieCont)
this.cookieCont = cookieCont;
public void AddBindingParameters(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Channels
.BindingParameterCollection bindingParameters)
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Dispatcher.ClientRuntime behavior)
behavior.MessageInspectors.Add(new CookieMessageInspector(cookieCont));
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Dispatcher
.EndpointDispatcher endpointDispatcher)
public void Validate(ServiceEndpoint serviceEndpoint)
消息检查器在BeforeSendRequest
方法中向服务器发送请求时添加cookie,并在AfterReceiveReply
方法中检索应更新的cookie。注意BeforeSendRequest
返回的correlationState
用于检索AfterReceiveReply
中的Uri:
public class CookieMessageInspector : IClientMessageInspector
private CookieContainer cookieCont;
public CookieMessageInspector(CookieContainer cookieCont)
this.cookieCont = cookieCont;
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,
object correlationState)
object obj;
if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out obj))
HttpResponseMessageProperty httpResponseMsg = obj as HttpResponseMessageProperty;
if (!string.IsNullOrEmpty(httpResponseMsg.Headers["Set-Cookie"]))
cookieCont.SetCookies((Uri)correlationState, httpResponseMsg.Headers["Set-Cookie"]);
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
System.ServiceModel.IClientChannel channel)
object obj;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out obj))
HttpRequestMessageProperty httpRequestMsg = obj as HttpRequestMessageProperty;
SetRequestCookies(channel, httpRequestMsg);
else
var httpRequestMsg = new HttpRequestMessageProperty();
SetRequestCookies(channel, httpRequestMsg);
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMsg);
return channel.RemoteAddress.Uri;
private void SetRequestCookies(System.ServiceModel.IClientChannel channel, HttpRequestMessageProperty httpRequestMessage)
httpRequestMessage.Headers["Cookie"] = cookieCont.GetCookieHeader(channel.RemoteAddress.Uri);
【讨论】:
重要的是,如果也设置了打开您的 app.config 文件并将 allowCookies="true" 添加到绑定中。
类似这样的:
<binding allowCookies="true" />
【讨论】:
鉴于这里获得赏金的最佳答案是如此复杂,这似乎不太可能是答案,但至少对于需要 cookie 才能运行的 eTapestry 的 API,这就是它所需要的。 哇...旧答案但完美。简单战胜了疯狂的复杂性。我正在使用需要登录的 SOAP API (InsideSales),该登录为所有未来的调用设置会话 cookie。这就是我所需要的。 这两个答案都是最好的。当您需要为在同一服务参考上执行的所有操作共享 cookie 时,此答案适用。但是,当您想在多个服务引用之间共享一个 cookie 时,赏金中奖的答案就会发挥作用。 这绝对是正确答案,但在 Google 上很容易被忽略。再说一遍 - 对于关键字 - 如果您需要在 .net 应用程序中的 webservice 中维护 windows 应用程序中的会话(相当于“在 SoapUI 中维护 http 会话”),只需输入此文件并将其粘贴到那里即可。仅此而已:-) 如果您自己管理 cookie,则必须设置allowCookies="false"
,如下所述:megakemp.com/2009/02/06/managing-shared-cookies-in-wcf【参考方案3】:
在这里找到解决方案:
http://msdn.microsoft.com/en-us/library/bb628649.aspx
事实证明我需要的是网络参考而不是服务参考
【讨论】:
呃,不,你没有。你为什么认为你会这样做? 同意,Web References 只是旧版本。改用上面@Markus 的答案以上是关于我在哪里设置服务引用上的 CookieContainer?的主要内容,如果未能解决你的问题,请参考以下文章