2013-03-02 50 views
4

我希望我的WCF响应具有使用DataContracts的两个名称空间的响应元素,但是我无法使其工作。这是我想什么反应是:控制WCF响应格式和名称空间

<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> 

这是我得到(与WCF测试客户端进行测试时)响应:

<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> 

我的服务界面看起来是这样的:

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

服务类:

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

而且DataContract类:

[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; } 
} 

我的WCF项目的目标框架是.NET 4的命名空间前缀不必是相同的。我如何以我想要的格式获得回复?

回答

1

要@Maikel 的TestReply是在默认的命名空间,所以没有前缀,但元件内部确实有它。

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

所以这个命名空间的前缀是a。 (因为'a ='),它与默认名称空间不同。

在你的方法ServiceContractAttribute的

GetDataResponse GetData(string name); 

为@Carlos建议,你可以写

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

你不能有这个

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

如果您想从响应中删除“wrapping”元素,则需要使用[MessageContract]。下面的代码显示了如何完成的一种方式。你可以使用服务/消息/数据合同中的命名空间来匹配你想要的。

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(); 
    } 
} 
+0

感谢您快速的解答,这是几乎是我想要的。 XML的布局正是我想要的,但元素没有“a:”前缀......任何想法? – 2013-03-03 08:06:36

+0

没有简单的方法来自定义WCF生成的XML中的*前缀* - 前缀应该仅用于定义名称空间,并且您通常不会选择使用哪个前缀。如果你真的想定制它们,你可以做到这一点,但这不是微不足道的 - http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml -responses.aspx显示了一种做法。 – carlosfigueira 2013-03-03 22:09:33

+0

对不起,我不是这个意思。我不介意前缀是“a”,但我希望节点(因此也是身体的第一个子节点)也具有它:。在使用您的代码时,内的所有节点都有前缀(这很好),但节点本身没有。 – 2013-03-04 08:19:44