Controlling WCF response format and namespaces

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

I want my WCF response to have a response element with two namespaces using DataContracts, but I can't get it to work. This is what I would like the response to be:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema">   <s:Header />   <s:Body>     <ns2:TestReply xmlns="http://www.test.org/test/2007/00" xmlns:ns2="http://www.test2.org/test2/types">       <ns2:Result>         <ns2:ActionSuccessful>true</ns2:ActionSuccessful>       </ns2:Result>       <ns2:ResultData>         <ns2:Name>Maikel Willemse</ns2:Name>       </ns2:ResultData>     </ns2:TestReply>   </s:Body> </s:Envelope>

This is the response I get (when testing with the WCF Test Client):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">   <s:Header />   <s:Body>     <GetDataResponse xmlns="http://www.test.org/test/2007/00">       <TestReply xmlns:a="http://www.test2.org/test2/types" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">         <a:Result>           <a:ActionSuccessful>true</a:ActionSuccessful>         </a:Result>         <a:ResultData>           <a:Name>Maikel Willemse</a:Name>         </a:ResultData>       </TestReply>     </GetDataResponse>   </s:Body> </s:Envelope>

My service interface looks like this:

[ServiceContract(Namespace = "http://www.test.org/test/2007/00")] public interface IService1 {     [OperationContract]     [return: MessageParameter(Name = "TestReply")]     GetDataResponse GetData(string name); }

The service class:

public class Service1 : IService1 {     public GetDataResponse GetData(string name)     {         return new GetDataResponse             {                 Result = new Result {ActionSuccessful = true},                 ResultData = new ResultData {Name = name}             };     } }

And the DataContract classes are:

[DataContract(Namespace = "http://www.test2.org/test2/types")] public class GetDataResponse {     [DataMember(Name = "Result")]     public Result Result { get; set; }      [DataMember(Name = "ResultData")]     public ResultData ResultData { get; set; } }  [DataContract(Namespace = "http://www.test2.org/test2/types")] public class Result {     [DataMember(Name = "ActionSuccessful")]     public bool ActionSuccessful { get; set; } }  [DataContract(Namespace = "http://www.test2.org/test2/types")] public class ResultData {     [DataMember(Name = "Name")]     public string Name { get; set; } }

The target framework of my WCF project is .NET 4. The namespace prefixes do not have to be the same. How can I get the response in the format I want?

回答1:

To @Maikel The TestReply is in the default namespace so there is no prefix, but the elements inside do have it.

xmlns:a="http://www.test2.org/test2/types

so the prefix for this namespace is a. (because of 'a=') and it is different from the default namespace.

In the ServiceContractAttribute of your method

GetDataResponse GetData(string name); 

as @Carlos suggested, you can write

[ServiceContract(Namespace="http://www.test2.org/test2/types")]

You cannot have this

<a:TestReply xmnls:a="http://www.test2.org/test2/types">


回答2:

If you want to remove the "wrapping" element from the response, you'll need to use a [MessageContract]. The code below shows one way how it can be done. And you can play with the namespaces in the service / message / data contracts to match what you want.

public class StackOverflow_15173138 {     [ServiceContract(Namespace = "http://www.test.org/test/2007/00")]     public interface IService1     {         [OperationContract]         MyResponse GetData(MyRequest request);     }      public class Service1 : IService1     {         public MyResponse GetData(MyRequest request)         {             return new MyResponse             {                 TestReply = new GetDataResponse                 {                     Result = new Result { ActionSuccessful = true },                     ResultData = new ResultData { Name = request.name }                 }             };         }     }      [MessageContract(IsWrapped = false)]     public class MyResponse     {         [MessageBodyMember]         public GetDataResponse TestReply { get; set; }     }      [MessageContract(WrapperName = "GetData")]     public class MyRequest     {         [MessageBodyMember]         public string name { get; set; }     }      [DataContract(Namespace = "http://www.test2.org/test2/types")]     public class GetDataResponse     {         [DataMember(Name = "Result")]         public Result Result { get; set; }          [DataMember(Name = "ResultData")]         public ResultData ResultData { get; set; }     }      [DataContract(Namespace = "http://www.test2.org/test2/types")]     public class Result     {         [DataMember(Name = "ActionSuccessful")]         public bool ActionSuccessful { get; set; }     }      [DataContract(Namespace = "http://www.test2.org/test2/types")]     public class ResultData     {         [DataMember(Name = "Name")]         public string Name { get; set; }     }      public static void Test()     {         string baseAddress = "http://" + Environment.MachineName + ":8000/Service";         ServiceHost host = new ServiceHost(typeof(Service1), new Uri(baseAddress));         host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "");         host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });         host.Open();         Console.WriteLine("Host opened");          ChannelFactory<IService1> factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress));         IService1 proxy = factory.CreateChannel();         Console.WriteLine(proxy.GetData(new MyRequest { name = "hello" }));          ((IClientChannel)proxy).Close();         factory.Close();          Console.Write("Press ENTER to close the host");         Console.ReadLine();         host.Close();     } }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!