【问题标题】:WCF MessageContract wrapping and listsWCF MessageContract 包装和列表
【发布时间】:2012-11-24 06:03:46
【问题描述】:

我收到了一位客户关于他们的网络服务客户端如何工作的规范。规范是从服务以及相应的 XSD 发送和接收的实际 SOAP XML 消息。客户希望我实施符合客户要求的 Web 服务。客户端是用axis2 ws-stack编写的,我想做的是在WCF中创建一个Web服务,它将接受客户端发出的请求并返回符合他们期望的XML的响应。在这个问题中,我只会发布与请求相关联的 XML 和 XSD,因为如果我能让它工作,将以类似的方式做出响应。

我收到的 XML 如下:

POST /axis2/services/SampleService HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: "sendCommand"
User-Agent: Axis2
Host: 127.0.0.1:7777
Content-Length: 347
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
   <soapenv:Body> 
      <SendCommandRequest xmlns="http://something.org/"> 
         <CMD> 
            <Station Address="ABC"> 
               <Platform Address="DEF"> 
                  <Command>5</Command> 
               </Platform> 
             </Station> 
         </CMD> 
       </SendCommandRequest> 
    </soapenv:Body>
</soapenv:Envelope>

这是对应的 XSD 的样子:

<xsd:complexType name="SendCommandRequestType"> 
    <xsd:sequence>  
        <xsd:element name="Station"> 
            <xsd:complexType> 
                <xsd:attribute name="Address" type="xsd:string" use="required" /> 
                <xsd:sequence> 
                    <xsd:element minOccurs="0" maxOccurs="1" name="Platform"> 
                        <xsd:complexType> 
                            <xsd:attribute name="Address" type="xsd:string" use="required" /> 
                            <xsd:sequence> 
                                <xsd:element name="Command"> 
                                    <xsd:simpleType> 
                                        <xsd:restriction base="xsd:string"> 
                                            <xsd:enumeration value="-1"/> 
                                            <xsd:enumeration value="0"/> 
                                            <xsd:enumeration value="1"/> 
                                            <xsd:enumeration value="2"/> 
                                            <xsd:enumeration value="3"/> 
                                            <xsd:enumeration value="4"/> 
                                            <xsd:enumeration value="5"/> 
                                        </xsd:restriction> 
                                    </xsd:simpleType> 
                                </xsd:element> 
                            </xsd:sequence> 
                        </xsd:complexType> 
                    </xsd:element> 
                </xsd:sequence> 
            <xsd:complexType>
        </xsd:element>
    </xsd:sequence>
</xsd:complexType>

我已经开始编写 WCF/MessageContract 格式的类型,但我在处理列表等方面遇到了困难,因为它们是双重包装的。

我的 MessageContracts 如下所示:

[MessageContract(WrapperName = "SendCommandRequest", WrapperNamespace = "http://something.org/")]
public class SendCommandRequest
{
    [MessageBodyMember(Name="CMD")]
    public CMD cmd = new CMD();
}

[MessageContract(IsWrapped=false)]
public class CMD
{
    [MessageBodyMember(Name="Station")]
    public List<Station> stations = new List<Station>();
}

[MessageContract(IsWrapped=false)]
public class Station
{

    [MessageBodyMember]
    public List<Platform> platforms = new List<Platform>();
    [MessageBodyMember(Name="Address")]
    public String Address; 
}

[MessageContract(WrapperName = "Platform")]
public class Platform
{
    [MessageBodyMember(Name = "Address")]
    public String Address;
}

当我使用 SoapUI 时,我从 web 服务收到以下响应:

 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <SendCommandRequest xmlns="http://ttraflinariawebservice.org/">
         <CMD xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/GeldImport" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:stations>
               <a:Station>
                  <a:Address>test</a:Address>
                  <a:platforms>
                     <a:Platform>
                        <a:Address>b</a:Address>
                     </a:Platform>
                  </a:platforms>
               </a:Station>
            </a:stations>
         </CMD>
      </SendCommandRequest>
   </s:Body>
</s:Envelope>

如您所见,它不符合客户期望的 XML 格式。如何让 MessageContract 符合客户期望的 XML?我不知何故需要让列表不像他们那样双重包装,并且类的属性似乎被添加到类名中。

如果您希望我提供更多信息和代码,我可以这样做。不想用可能与问题无关的内容填满整个帖子。

编辑:

提供的 XSD 文件格式不正确。为了解决这个问题,我从提供的 XML 文件中重新生成了一个 XSD。然后我使用 WSCF.blue 工具为 XSD 生成数据协定代码。

我进行了更改,以便服务合同使用 doc litteral 格式以符合axis2 soap1.1

[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document, SupportFaults = true)]
[ServiceContract]
public interface MyService

我还将操作合同更改为将 System.ServiceModel.Channels.Message 作为输入和输出消息,然后使用生成的类(我从 XSD 生成)手动序列化和反序列化 xml。

【问题讨论】:

    标签: c# wcf web-services xsd messagecontract


    【解决方案1】:

    您最初尝试的问题是您尝试使用[MessageContract] 类来定义消息的数据 合同(模式)。消息契约仅用作最顶层的类(定义进入消息头的内容和进入正文的内容)。其他类需要使用您正在使用的序列化程序的属性(并且由于您有 XML 属性,因此您需要使用 XmlSerializer)。下面的代码显示了如何获得与您提供的模式兼容的对象模型。您可以使用 Fiddler 等工具查看它发送的请求。

    public class StackOverflow_13739729
    {
        [ServiceContract(Namespace = "http://something.org")]
        public interface ITest
        {
            [XmlSerializerFormat, OperationContract(Name = "sendCommand")]
            void SendCommand(SendCommandRequest req);
        }
    
        public class Service : ITest
        {
            public void SendCommand(SendCommandRequest req)
            {
                Console.WriteLine("In service");
            }
        }
    
        [MessageContract(WrapperName = "SendCommandRequest", WrapperNamespace = "http://something.org")]
        public class SendCommandRequest
        {
            [MessageBodyMember]
            public CMD CMD { get; set; }
        }
    
        [XmlType]
        public class CMD
        {
            [XmlElement]
            public Station Station { get; set; }
        }
    
        public class Station
        {
            [XmlAttribute]
            public string Address { get; set; }
    
            [XmlElement]
            public Platform Platform { get; set; }
        }
    
        public class Platform
        {
            string[] validCommands = new[] { "-1", "0", "1", "2", "3", "4", "5" };
            string[] command;
    
            [XmlAttribute]
            public string Address { get; set; }
    
            [XmlElement]
            public string[] Command
            {
                get { return this.command; }
                set
                {
                    if (value != null)
                    {
                        if (!value.All(c => validCommands.Contains(c)))
                        {
                            throw new ArgumentException("Invalid command");
                        }
                    }
    
                    this.command = value;
                }
            }
        }
    
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
            host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
            host.Open();
            Console.WriteLine("Host opened");
    
            ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
            ITest proxy = factory.CreateChannel();
    
            SendCommandRequest req = new SendCommandRequest
            {
                CMD = new CMD
                {
                    Station = new Station
                    {
                        Address = "ABC",
                        Platform = new Platform
                        {
                            Address = "DEF",
                            Command = new string[] { "5" }
                        }
                    }
                }
            };
    
            proxy.SendCommand(req);
    
            ((IClientChannel)proxy).Close();
            factory.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多