Returning XmlDocument from WCF service not working

2019-03-06 02:54发布

问题:

I am trying to update some WCF service methods that return strings to return XmlDocument objects. I've tried returning it as-is and encapsulating it in a datacontract object. Either way I'm hitting an error upon attempting to update the service reference. The error suggest encapsulating it in a datacontract with an operations contract which I am doing. Is there a trick to this?

回答1:

There's a way to return a XmlDocument from WCF, but you need to use the XmlSerializer instead of the default serializer (DataContractSerialier) - the code below shows how it can be done. Having said that, do consider using data transfer objects as mentioned in the comments, unless your scenario really requires a XmlDocument to be transferred.

public class StackOverflow_8951319
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
        [OperationContract, XmlSerializerFormat]
        XmlDocument GetDocument();
    }
    public class Service : ITest
    {
        public string Echo(string text)
        {
            return text;
        }

        public XmlDocument GetDocument()
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(@"<products>
  <product id='1'>
    <name>Bread</name>
  </product>
  <product id='2'>
    <name>Milk</name>
  </product>
  <product id='3'>
    <name>Coffee</name>
  </product>
</products>");
            return doc;
        }
    }
    static Binding GetBinding()
    {
        var result = new WSHttpBinding(SecurityMode.None);
        //Change binding settings here
        return result;
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(ITest), GetBinding(), "");
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine(proxy.Echo("Hello"));

        Console.WriteLine(proxy.GetDocument().OuterXml);

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

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}


回答2:

If you want to be able to pass arbitrary XML on the wire the best way to do it is to use XElement rather than XmlDocument

XmlDocument isn't serializable