c# - 在哪里设置服务引用上的 CookieContainer?

标签 c# web-services asmx service-reference web-reference

例如,在 .NET 2.0 项目上将 WebService 引用添加到 ASMX 服务时,

var objService = new NameSpace.groupservices();

存在,

objService.CookieContainer = new System.Net.CookieContainer();

例如,在 .NET 4.0 项目上将 ServiceReference 添加到 ASMX 服务时,

var objService = new NameSpace.groupservicesSoapClient();

objService 没有任何 CookieContainer 属性

有人问了类似的问题here没有正解。

有人可以指导在哪里可以找到该属性(property)吗?

最佳答案

与绑定(bind)到 HTTP 传输的 ASMX Web 服务相比,WCF 允许使用各种传输协议(protocol)。因此,并非所有特定于协议(protocol)的选项(例如用于 HTTP 传输的 Cookie)在 WCF 服务引用中都可用。

但是,您可以添加一个消息检查器来检查在客户端和服务器之间发送的消息。这article描述了一种将 cookie 发送到服务器的方法。

我已经扩展示例以使用 CookieContainer。此外,以下代码显示了如何评估服务器发送的 Set-Cookie header 以将新 cookie 添加到容器中。请注意,示例显示了一个基本轮廓,但可能需要扩展或更多验证。但是,在一个简单的场景中它起作用了。

以下片段显示了托管在 IIS 上并集成在 ASP.NET 框架中的 WCF 服务的测试方法。它基本上以字符串形式回显发送到服务器的 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);
    }
}

关于c# - 在哪里设置服务引用上的 CookieContainer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18411823/

相关文章:

c# - 如何用 C# 语言呈现一个 5 位数字(十六进制)的字符 Unicode

c# - 创建基本用户控件

c# - NavigationService 删除 forwardstack

asp.net - "The provided URI scheme ' https ' is invalid; expected ' http '. Parameter name: via"- 帮助?

c# - 以编程方式获取由 *.asmx/js 生成的 JavaScript

c# - asmx 网络服务 : client authentication

c# - visual studio 在处理异常时中断

java - 如何获取系统中的方面列表

java - 安全的 Java Web 服务

jquery - 使用 jQuery 调用 Web 服务以返回简单的 bool 值