控制WCF响应格式和名称空间

时间:2013-03-02 09:57:42

标签: c# wcf

我希望我的WCF响应有一个带有两个名称空间的响应元素,使用DataContracts,但我无法让它工作。这就是我想要的回应:

<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.名称空间前缀不必相同。如何以我想要的格式获得响应?

2 个答案:

答案 0 :(得分:5)

如果要从响应中删除“wrap”元素,则需要使用[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();
    }
}

答案 1 :(得分: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">