0

I'm trying to create a very simple web service that will accept an Xml file. The simplest way, in my mind, is to create a method that accepts an XmlDocument object as a parameter. My code for the service looks like this:

namespace MercuryWebSvc
{

    public class MercuryWebSvc : IMercuryWebSvc
    {
        public void sendData(XmlDocument x)
        {
            XDocument xd = x.ToXDocument();

            var att = xd.Root.Attributes();
            Console.WriteLine(att.ToString());

        }

    }

    public static class DocumentExtension
    {
        public static XDocument ToXDocument(this XmlDocument xmld)
        {
            using (var xmlReader = new XmlNodeReader(xmld))
            {
                xmlReader.MoveToContent();
                return XDocument.Load(xmlReader);
            }
        }
    }
}

The IMercuryWebSvc interface:

[ServiceContract]
public interface IMercuryWebSvc
{
    [OperationContract]
    [ServiceKnownType(typeof(XmlDocument[]))]
    void sendData(XmlDocument x);
}

When I build the project and use the wsdl file to create a client to test the code, the resulting method looks like this:

public void sendData(object[] x)
{
    base.Channel.sendData(x);
}

For some reason, the svcutil tool has changed the accepted parameter type from XmlDocument to object[]. This is causing me to get the following exception:

System.ServiceModel.CommunicationException was unhandled
  HResult=-2146233087
  Message=There was an error while trying to serialize parameter http://tempuri.org/:x. The InnerException message was 'Type 'System.Xml.XmlDocument' with data contract name 'ArrayOfanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.'.  Please see InnerException for more details.
  Source=mscorlib
  StackTrace:
    Server stack trace: 
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
       at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
       at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer)
       at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at IMercuryWebSvc.sendData(Object[] x)
       at MercuryWebSvcClient.sendData(Object[] x) in c:\users\#name\documents\visual studio 2015\Projects\MercuryWebSvc\MercurySvcClient\MercuryWebSvcRef.cs:line 62
       at MercurySvcClient.Program.Main(String[] args) in c:\users\#name\documents\visual studio 2015\Projects\MercuryWebSvc\MercurySvcClient\Program.cs:line 22
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
       HResult=-2146233076
       Message=Type 'System.Xml.XmlDocument' with data contract name 'ArrayOfanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.
       Source=System.Runtime.Serialization
       StackTrace:
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
            at WriteArrayOfanyTypeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
            at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
            at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType)
            at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
            at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
            at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
            at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
            at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
       InnerException: 

I've read a few threads and tried adding a KnownTypeAttribute(typeof(XmlDocument[])) to my class with no success. Same with just plain KnownTypeAttribute(typeof(XmlDocument)) (not an array). What do I need to do to be able to pass an XmlDocument successfully through this method?

EDIT: Added additional KnownTypeAttribute for non-array object.

Inagnikai
  • 281
  • 1
  • 15
  • Why is the argument an XmlDocument but the ServiceKnownTypeAttribute is given an array type (XmlDocument[])? That seems weird right there. –  Jan 19 '17 at 15:51
  • I tried using just plain XmlDocument as well. Same result – Inagnikai Jan 19 '17 at 15:55
  • Are you saying you tried KnownTypeAttribute(typeof(**XmlDocument**)) (note, no []) –  Jan 19 '17 at 15:56
  • Yes, that is correct. I edited my post to reflect that. – Inagnikai Jan 19 '17 at 15:56
  • 2
    Not familiar with the tool, but if I had to wager, svcutil just can't handle XmlDocument correctly. Hell, I don't even think XmlDocument can be sent through a wcf service... yeah, a quick search reveals this http://stackoverflow.com/questions/964870/wcf-return-an-xmldocument I'd suggest trying what the selected answer suggests (System.Xml.Linq types are better for working with xml anyhow). Alternatively, ditch trying to send/receive complex types and send the xml as a string. –  Jan 19 '17 at 16:05
  • This does appear to be the easiest way to solve this issue. Would you mind putting it in an answer so I can mark it as the solution? – Inagnikai Jan 19 '17 at 16:33

0 Answers0