WCF MessageContract包装和列表

我收到了客户关于他们的网络服务客户端如何工作的规范。 规范是从服务发送和接收的实际SOAP XML消息以及相应的XSD。 客户希望我实施符合客户要求的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        5       

这是相应的XSD的样子:

                                

我已经开始用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 stations = new List(); } [MessageContract(IsWrapped=false)] public class Station { [MessageBodyMember] public List platforms = new List(); [MessageBodyMember(Name="Address")] public String Address; } [MessageContract(WrapperName = "Platform")] public class Platform { [MessageBodyMember(Name = "Address")] public String Address; } 

当我使用SoapUI时,我从Web服务获得以下响应:

        test   b         

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

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

编辑:

提供的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。

原始尝试的问题是您尝试使用[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 factory = new ChannelFactory(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(); } }