WCF & IXmlSerializable: корневой элемент заменяется в ответ - PullRequest
2 голосов
/ 20 октября 2011

У нас есть настраиваемая XML-сериализация для нашего «протокола» здесь:

[XmlRoot("axf", Namespace = Axf10Namespace)]
public class AxfDocument : IXmlSerializable
{
  public const string Axf10Namespace = "http://schemas.***.ru/axf/axf-1.0.0";
  // ...
}

и все нормально при использовании стандартного .NET XmlSerializer:

<?xml version="1.0" encoding="utf-16"?>
<axf version="1.0.0" createdAt="2011-10-20T13:11:40" xmlns="http://schemas.***.ru/axf/axf-1.0.0">
  <itineraries>
    <!-- -->
   </itineraries>
</axf>

Теперь, когда мы пытаемсяиспользуйте этот класс в пустой службе WCF:

[OperationContract]
AxfDocument GetItineraries(ItinerariesQuery query);

фактический документ XML, который отправляется на сторону клиента, выглядит следующим образом:

<GetItinerariesResult version="1.0.0" createdAt="2011-10-20T13:17:50" xmlns="http://tempuri.org/">
  <itineraries xmlns="http://schemas.***.ru/axf/axf-1.0.0">
    <!-- rest is fine, serialization code does work -->

Как согнуть WCF для отправки корневого элементакак есть и не заменить его своим?

1 Ответ

1 голос
/ 21 октября 2011

По умолчанию ответы на операции заключены в имя операции. Однако вы можете использовать MessageContract в определении операции, чтобы использовать развернутый ответ, как показано ниже. Если вы посмотрите на тело ответа на запрос в Fiddler, то увидите, что он точно такой же, как и в сериализации.

public class StackOverflow_7836645
{
    [XmlRoot("axf", Namespace = Axf10Namespace)]
    public class AxfDocument : IXmlSerializable
    {
        public const string Axf10Namespace = "http://schemas.something.ru/axf/axf-1.0.0";

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("intineraries", Axf10Namespace);
            writer.WriteElementString("item", Axf10Namespace, "one value");
            writer.WriteElementString("item", Axf10Namespace, "another value");
            writer.WriteEndElement();
        }
    }

    [MessageContract(IsWrapped = false)]
    public class OperationResponse
    {
        [MessageBodyMember(Name = "axf", Namespace = AxfDocument.Axf10Namespace)]
        public AxfDocument axf;
    }

    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        OperationResponse GetAxf();
    }

    public class Service : ITest
    {
        public OperationResponse GetAxf()
        {
            return new OperationResponse { axf = new AxfDocument() };
        }
    }

    public static void Test()
    {
        Console.WriteLine("Serialization");
        MemoryStream ms = new MemoryStream();
        XmlSerializer xs = new XmlSerializer(typeof(AxfDocument));
        xs.Serialize(ms, new AxfDocument());
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        Console.WriteLine();
        Console.WriteLine("Service");

        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<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine(proxy.GetAxf());

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...