2013-03-02 2 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 Test):

<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 ​​='), и он отличается от пространства имен по умолчанию.

В 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]. В приведенном ниже коде показано, как это можно сделать. И вы можете играть с пространствами имен в контрактах service/message/data, чтобы соответствовать тому, что вы хотите.

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:» ... Любые идеи? –

+0

Нет простого способа настроить * префиксы * в XML, сгенерированные WCF, префикс должен использоваться для определения пространства имен, и обычно вы не можете выбрать, какой префикс используется. Если вы действительно хотите их настроить, вы можете это сделать, но это не тривиально - сообщение в http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml -responses.aspx показывает один из способов сделать это. – carlosfigueira

+0

Простите, это не то, что я имел в виду. Я не против префикса, который является «а», но я хотел бы, чтобы узел (так что первый дочерний узел тела) также имел его: . При использовании вашего кода все узлы внутри имеют префикс (что хорошо), но сам узел этого не делает. –

Смежные вопросы