使用CookieContainer的WCF Web服务客户端

7

我开发了一个小型的C#表单应用程序,它调用了一个Web服务。一切都很好,但是我需要保持状态,为此我需要使用CookieContainer(如果我没有弄错的话)。

我使用项目的“添加服务引用”菜单创建了服务引用,一切都很顺利。但我不知道如何在创建的客户端上添加CookieManager。

我找到了一些示例,这些示例显示了一些样本,例如:

serviceClient.CookieContainer=new CookieContainer()

但事实并非如此。我的服务客户端没有这样的属性。顺便说一下,我正在使用 Visual Studio 2010 Beta。
提前感谢!
这是生成的 ServiceReference(自动生成的):
//------------------------------------------------------------------------------

// // 这段代码是由一个工具生成的。 // 运行时版本:4.0.30128.1 // // 如果更改此文件可能会导致不正确的行为,并且如果重新生成代码,则更改将丢失。 // //------------------------------------------------------------------------------

命名空间 WSClient.SecurityServiceReference {

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://max/", ConfigurationName="SecurityServiceReference.SecurityService")]
public interface SecurityService {

    // CODEGEN: Generating message contract since element name return from namespace  is not marked nillable
    [System.ServiceModel.OperationContractAttribute(Action="http://max/SecurityService/nextValRequest", ReplyAction="http://max/SecurityService/nextValResponse")]
    [System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Allowed)]
    WSClient.SecurityServiceReference.nextValResponse nextVal(WSClient.SecurityServiceReference.nextValRequest request);

    // CODEGEN: Generating message contract since element name return from namespace  is not marked nillable
    [System.ServiceModel.OperationContractAttribute(Action="http://max/SecurityService/reportSessionIDRequest", ReplyAction="http://max/SecurityService/reportSessionIDResponse")]
    [System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Allowed)]
    WSClient.SecurityServiceReference.reportSessionIDResponse reportSessionID(WSClient.SecurityServiceReference.reportSessionIDRequest request);
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class nextValRequest {

    [System.ServiceModel.MessageBodyMemberAttribute(Name="nextVal", Namespace="http://max/", Order=0)]
    public WSClient.SecurityServiceReference.nextValRequestBody Body;

    public nextValRequest() {
    }

    public nextValRequest(WSClient.SecurityServiceReference.nextValRequestBody Body) {
        this.Body = Body;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class nextValRequestBody {

    public nextValRequestBody() {
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class nextValResponse {

    [System.ServiceModel.MessageBodyMemberAttribute(Name="nextValResponse", Namespace="http://max/", Order=0)]
    public WSClient.SecurityServiceReference.nextValResponseBody Body;

    public nextValResponse() {
    }

    public nextValResponse(WSClient.SecurityServiceReference.nextValResponseBody Body) {
        this.Body = Body;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.Runtime.Serialization.DataContractAttribute(Namespace="")]
public partial class nextValResponseBody {

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
    public string @return;

    public nextValResponseBody() {
    }

    public nextValResponseBody(string @return) {
        this.@return = @return;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class reportSessionIDRequest {

    [System.ServiceModel.MessageBodyMemberAttribute(Name="reportSessionID", Namespace="http://max/", Order=0)]
    public WSClient.SecurityServiceReference.reportSessionIDRequestBody Body;

    public reportSessionIDRequest() {
    }

    public reportSessionIDRequest(WSClient.SecurityServiceReference.reportSessionIDRequestBody Body) {
        this.Body = Body;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class reportSessionIDRequestBody {

    public reportSessionIDRequestBody() {
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class reportSessionIDResponse {

    [System.ServiceModel.MessageBodyMemberAttribute(Name="reportSessionIDResponse", Namespace="http://max/", Order=0)]
    public WSClient.SecurityServiceReference.reportSessionIDResponseBody Body;

    public reportSessionIDResponse() {
    }

    public reportSessionIDResponse(WSClient.SecurityServiceReference.reportSessionIDResponseBody Body) {
        this.Body = Body;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.Runtime.Serialization.DataContractAttribute(Namespace="")]
public partial class reportSessionIDResponseBody {

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
    public string @return;

    public reportSessionIDResponseBody() {
    }

    public reportSessionIDResponseBody(string @return) {
        this.@return = @return;
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface SecurityServiceChannel : WSClient.SecurityServiceReference.SecurityService, System.ServiceModel.IClientChannel {
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class SecurityServiceClient : System.ServiceModel.ClientBase<WSClient.SecurityServiceReference.SecurityService>, WSClient.SecurityServiceReference.SecurityService {

    public SecurityServiceClient() {
    }

    public SecurityServiceClient(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    public SecurityServiceClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public SecurityServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public SecurityServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }

    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    WSClient.SecurityServiceReference.nextValResponse WSClient.SecurityServiceReference.SecurityService.nextVal(WSClient.SecurityServiceReference.nextValRequest request) {
        return base.Channel.nextVal(request);
    }

    public string nextVal() {
        WSClient.SecurityServiceReference.nextValRequest inValue = new WSClient.SecurityServiceReference.nextValRequest();
        inValue.Body = new WSClient.SecurityServiceReference.nextValRequestBody();
        WSClient.SecurityServiceReference.nextValResponse retVal = ((WSClient.SecurityServiceReference.SecurityService)(this)).nextVal(inValue);
        return retVal.Body.@return;
    }

    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    WSClient.SecurityServiceReference.reportSessionIDResponse WSClient.SecurityServiceReference.SecurityService.reportSessionID(WSClient.SecurityServiceReference.reportSessionIDRequest request) {
        return base.Channel.reportSessionID(request);
    }

    public string reportSessionID() {
        WSClient.SecurityServiceReference.reportSessionIDRequest inValue = new WSClient.SecurityServiceReference.reportSessionIDRequest();
        inValue.Body = new WSClient.SecurityServiceReference.reportSessionIDRequestBody();
        WSClient.SecurityServiceReference.reportSessionIDResponse retVal = ((WSClient.SecurityServiceReference.SecurityService)(this)).reportSessionID(inValue);
        return retVal.Body.@return;
    }
}

}


为了让我创建的服务客户端具有CookieContainer属性,我不得不创建一个WebReference(.NET 2.0-查看向导表单底部的兼容性标题),但我需要使用VS2010默认方式来完成。有什么想法吗? - Timmo
4个回答

13

1
我找到了唯一的功能性解决方案,它运行得非常好。 - David
Link的简短信息(它有效):binding.AllowCookies = true; using(var webServiceProxy = new ReportExecutionServiceSoapClient(binding, endpoint)){} - Stefan Steiger
作为警告,链接中的集中管理解决方案对Cookie采取了非常简化的视图,并且不符合任何3个不同的Cookie RFC(2109、2965、6265),因此重要的是要了解您正在连接到的服务器的要求。例如,我曾经看到一个服务器按照2109发送多个逗号分隔的Cookie,但只包括它想要更新的那些。 - Shane Courtrille

0

1
您正在查看有关旧版 ASMX Web 服务的信息。除非必须,否则请勿使用它们。 - John Saunders

0

上面的回答只有一个非常有用的文章链接,但没有其他细节。
在StackOverflow上,仅链接唯一的答案并不受欢迎,因此这里是该文章的摘要

以下是文章的摘要

在WCF世界中,情况略有不同。 WCF作为一种传输无关技术,不允许直接反映cookie的概念在高级API中,因为它是特定于HTTP协议的。 实际上,这意味着Web服务客户端对象没有任何CookieContainer属性可设置和检索。

以下是WCF的解决方案(也适用于我)

private static void Main(object[] args)
{
    string sharedCookie;

    MyWebServiceClient client = new MyWebServiceClient();

    using (new OperationContextScope(client.InnerChannel))
    {
        client.DoSomething();

        // Extract the cookie embedded in the received web service response
        // and stores it locally
        HttpResponseMessageProperty response = (HttpResponseMessageProperty)
        OperationContext.Current.IncomingMessageProperties[
            HttpResponseMessageProperty.Name];
        sharedCookie = response.Headers["Set-Cookie"];
    }

    MyOtherWebServiceClient otherClient = new MyOtherWebServiceClient();

    using (new OperationContextScope(otherClient.InnerChannel))
    {
        // Embeds the extracted cookie in the next web service request
        // Note that we manually have to create the request object since
        // since it doesn't exist yet at this stage
        HttpRequestMessageProperty request = new HttpRequestMessageProperty();
        request.Headers["Cookie"] = sharedCookie;
        OperationContext.Current.OutgoingMessageProperties[
            HttpRequestMessageProperty.Name] = request;

        otherClient.DoSomethingElse();
    }
}

-3

这个服务引用是使用WCF创建的,而WCF独立于实际的通信媒介,这意味着这些服务可以使用WebService或Remoting或MSMQ。而Remoting和MSMQ没有Cookie的概念。

最好使用WSDL.exe创建您的Web服务引用,并将生成的类添加到您的项目中。我也是这样做的。


-1:建议不好。你建议他回到过去,以免学习现在。 - John Saunders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接