Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用基于第三方WSDL的消息契约正确生成服务引用,或者在WF服务项目中强制不生成消息契约_C#_Web Services_Visual Studio 2012_Wsdl_Workflow Foundation 4 - Fatal编程技术网

C# 如何使用基于第三方WSDL的消息契约正确生成服务引用,或者在WF服务项目中强制不生成消息契约

C# 如何使用基于第三方WSDL的消息契约正确生成服务引用,或者在WF服务项目中强制不生成消息契约,c#,web-services,visual-studio-2012,wsdl,workflow-foundation-4,C#,Web Services,Visual Studio 2012,Wsdl,Workflow Foundation 4,我有一个问题,给定第三方WSDL,我可以从控制台应用程序轻松创建一个有效的服务代理,但从WF4 WF服务我不能。后一种情况下生成的代理显然有缺陷,具体涉及两个问题: a) 消息协定总是在未请求或不需要时生成 b) 使用了不正确的响应消息和xml包装器名称,导致响应对象为空且反序列化失败 我面临的问题是在第三方WSDL的基础上实际生成Reference.cs类。在WSDL中有许多操作,按照出现的顺序,其中2个操作如下: 检查响应服务 服务处理(剪切) ... 向匹配系统插入指令 此服务(断开)

我有一个问题,给定第三方WSDL,我可以从控制台应用程序轻松创建一个有效的服务代理,但从WF4 WF服务我不能。后一种情况下生成的代理显然有缺陷,具体涉及两个问题: a) 消息协定总是在未请求或不需要时生成 b) 使用了不正确的响应消息和xml包装器名称,导致响应对象为空且反序列化失败

我面临的问题是在第三方WSDL的基础上实际生成Reference.cs类。在WSDL中有许多操作,按照出现的顺序,其中2个操作如下:


检查响应服务
服务处理(剪切)
...
向匹配系统插入指令
此服务(断开)
这会在Reference.cs中产生以下结果:

请注意,出于某种原因,mi102操作是使用pu013Response的错误响应消息生成的,声明如下:

 [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.MessageContractAttribute(WrapperName="pu013Response", WrapperNamespace="http://pse/", IsWrapped=true)]
    public partial class pu013Response { 
请注意,WrapperName阻止XML序列化程序识别响应,即mi102Response,因此对于所有不是pu013的操作,我总是得到空响应

此外,如果从控制台应用程序添加引用,则不会发生这种情况。这不会生成消息契约,在本例中,调用和响应是有效的

有什么不同?svcutil是否在幕后被调用?如果是,所使用的参数有什么不同?svcutil也可以用来生成xamlx活动,这样我就可以找到一个命令行解决方法了吗

这看起来像是VS/Add服务引用错误。另一种方法是手动更正Reference.cs中的许多操作

理想情况下,我正在寻找一种方法来轻松、自动地运行svcutil或添加服务引用,以便引用类正确并生成xamlx活动。一个很好的解释是为什么会有差异,以及在幕后发生了什么

更新
控制台应用程序中生成的消息协定会导致相同的问题-响应声明不正确。如果使用参数而不是消息(WF服务应用程序无法提供消息),问题就会消失。

我在这些问题上远远不是权威,尽管下面的回答可能不完全适合您的问题,我最近与服务建立proxyless连接的经验可能会为您或下一个有类似问题的人提供一些见解

首先,我想看看您是否可以使用fiddler手动滚动SOAP请求,看看您是否能够创建正确的消息并将其发送出去。因为您将自动化工具描述为有缺陷的(或者可能存在配置问题,您并没有得到正确的答案)。无论哪种方式,对合同的形式有一个清晰的理解,并且能够在fiddler中执行一个可靠的测试可以提供清晰的信息

您不一定需要依赖于使用代理。您可以创建自己的soap消息,并通过以下两种方式之一发送它。首先是使用ChannelFactory

  • 创建您的消息正文(如果需要,消息类可以与其他类一起工作)
  • 创建您的消息
  • 通过ChannelFactory发送您的消息
  • 对于步骤1,您可以通过制作一个简单的POCO来构建消息,以反映合同中的预期内容。您应该能够通过WSDL派生该类是什么

    假设服务是这样的:

    [ServiceContract(Namespace = "http://Foo.bar.car")]
    public interface IPolicyService
    {
        [OperationContract]
        PolicyResponse GetPolicyData(PolicyRequest request);
    }
    
    public class PolicyData : IPolicyService
    {
       public PolicyResponse GetPolicyData(PolicyRequest request)
       {
                var polNbr = request.REQ_POL_NBR;
                return GetMyData(polNbr);
        }
    }
    
    您需要这样一个类:

    [DataContract(Namespace = "http://Foo.bar.car")]
    public class GetPolicyData
    {
        [DataMember]
        public request request { get; set; }
    }
    
    [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy")]
    public class request
    {
        ///<summary>
        /// Define request parameter for SOAP API to retrieve selective Policy level data
        /// </summary>
        [DataMember]
        public string REQ_POL_NBR { get; set; }
    }
    
        private static Message SendMessage(string id)
        {
            var body = new GetPolicyData {request =  new request{ REQ_POL_NBR = id }}; 
            var message = Message.CreateMessage(MessageVersion.Soap11, "http://Foo.bar.car/IPolicyService/GetPolicyData", body);
    // these headers would probably not be required, but added for completeness
            message.Headers.Add(MessageHeader.CreateHeader("Accept-Header", string.Empty, "application/xml+"));
            message.Headers.Add(MessageHeader.CreateHeader("Content-Type", string.Empty, "text/xml"));
            message.Headers.Add(MessageHeader.CreateHeader("FromSender", string.Empty, "DispatchMessage"));
            message.Headers.To = new System.Uri(@"http://localhost:5050/PolicyService.svc");
    
            var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
            {
                 MessageEncoding = WSMessageEncoding.Text,
                MaxReceivedMessageSize = int.MaxValue,
                SendTimeout = new TimeSpan(1, 0, 0),
                ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue }
            };
            message.Properties.Add("Content-Type", "text/xml; charset=utf-8");
            message.Properties.Remove("Accept-Encoding");
            message.Properties.Add("Accept-Header", "application/xml+");
    
            var cf = new ChannelFactory<IRequestChannel>(binding, new EndpointAddress(new Uri("http://localhost:5050/PolicyService.svc")));
    
            cf.Open();
            var channel = cf.CreateChannel();
            channel.Open();
    
            var result = channel.Request(message);
    
            channel.Close();
            cf.Close();
            return result;
        }
    
    Post action:    http://localhost:5050/PolicyService.svc
    Header:
    User-Agent: Fiddler
    SOAPAction: http://Foo.bar.car/IPolicyService/GetPolicyData
    Content-type: text/xml
    Host: localhost:5050
    Content-Length: 381
    
    这被称为:

    return ClientHelper.Post("http://localhost:5050/PolicyService.svc", "http://Foo.bar.car/IPolicyService/GetPolicyData", "GetPolicyData", "REQ_POL_NBR", id);
    
    在Fiddler中测试它看起来像这样:

    [DataContract(Namespace = "http://Foo.bar.car")]
    public class GetPolicyData
    {
        [DataMember]
        public request request { get; set; }
    }
    
    [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy")]
    public class request
    {
        ///<summary>
        /// Define request parameter for SOAP API to retrieve selective Policy level data
        /// </summary>
        [DataMember]
        public string REQ_POL_NBR { get; set; }
    }
    
        private static Message SendMessage(string id)
        {
            var body = new GetPolicyData {request =  new request{ REQ_POL_NBR = id }}; 
            var message = Message.CreateMessage(MessageVersion.Soap11, "http://Foo.bar.car/IPolicyService/GetPolicyData", body);
    // these headers would probably not be required, but added for completeness
            message.Headers.Add(MessageHeader.CreateHeader("Accept-Header", string.Empty, "application/xml+"));
            message.Headers.Add(MessageHeader.CreateHeader("Content-Type", string.Empty, "text/xml"));
            message.Headers.Add(MessageHeader.CreateHeader("FromSender", string.Empty, "DispatchMessage"));
            message.Headers.To = new System.Uri(@"http://localhost:5050/PolicyService.svc");
    
            var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
            {
                 MessageEncoding = WSMessageEncoding.Text,
                MaxReceivedMessageSize = int.MaxValue,
                SendTimeout = new TimeSpan(1, 0, 0),
                ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue }
            };
            message.Properties.Add("Content-Type", "text/xml; charset=utf-8");
            message.Properties.Remove("Accept-Encoding");
            message.Properties.Add("Accept-Header", "application/xml+");
    
            var cf = new ChannelFactory<IRequestChannel>(binding, new EndpointAddress(new Uri("http://localhost:5050/PolicyService.svc")));
    
            cf.Open();
            var channel = cf.CreateChannel();
            channel.Open();
    
            var result = channel.Request(message);
    
            channel.Close();
            cf.Close();
            return result;
        }
    
    Post action:    http://localhost:5050/PolicyService.svc
    Header:
    User-Agent: Fiddler
    SOAPAction: http://Foo.bar.car/IPolicyService/GetPolicyData
    Content-type: text/xml
    Host: localhost:5050
    Content-Length: 381
    
    正文:

    
    1.
    
    同样,这个答案并不是试图解决如何以不同的方式调用svcuti,而是为了避免完全调用它,所以我希望编辑之神不会因此而责备我;-)

    我上面的代码是受到比我更好的开发人员的启发,但我希望它能有所帮助


    我建议您使用命令行实用程序生成wsdl代理,并在项目中添加生成的代理文件。它将在每个项目中工作,您可以从output.config中找到所需的配置,这些配置将从命令行实用程序生成


    如果您需要wsdl命令和选项,那么我可以为您提供。

    您是否尝试将其添加为Web引用而不是服务引用?它可以解决第三方服务的一些问题。看一看:在一个WF服务项目中,Web引用不可用。我已经设法在这一项目上与Microsoft打开了一张技术支持票证,所以我正在等待他们怎么说。这里有多个问题,其中之一是我从服务器(第三方)收到的实际SOAP消息也忽略了SimpleResponse,并发送回pu013Response、mi102Response等。我认为这是根据WSDL规范的默认行为。您是否尝试使用svcutil生成代理?这也提供了一种控制服务代理命名空间的好方法。我不确定这是否能解决您的问题,但我经历过,从VS添加服务/web引用有时会在代理文件中添加额外的代码。pu013Response确实具有相同的结构是。问题是,所有重用pu013Response的人都无法再对SOAP响应进行反序列化,而SOAP响应是。。。。这不是手动更正代理帮助的地方
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
    <GetPolicyData xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Foo.bar.car">
    <request xmlns:d4p1="http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy">
    <d4p1:REQ_POL_NBR>1</d4p1:REQ_POL_NBR>
    </request>
    </GetPolicyData>
      </s:Body>
    </s:Envelope>