Служба WCF SOAP изменяет имя элементов массива при (де) сериализации

#c# #wcf #serialization #soap

#c# #wcf #сериализация #soap

Вопрос:

У меня есть клиент (который не очень гибок в отправляемом им SOAP), который генерирует SOAP, подобный следующему, из метода с сигнатурой void Test(int[] test) :

 <?xml version="1.0" encoding="UTF-8" ?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SOAP:Body>
        <Test xmlns="http://www.mydomain.com/">
            <test>
                <item>1</item>
                <item>2</item>
                <item>3</item>
                <item>4</item>
                <item>5</item>
                <item>7</item>
            </test>
        </Test>
    </SOAP:Body>
</SOAP:Envelope>
  

Мне нужен мой веб-сервис WCF SOAP для правильной десериализации этого.

По умолчанию она выдает следующее исключение:

 System.ServiceModel.Dispatcher.NetDispatcherFaultException: The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'Test'. End element 'test' from namespace 'http://www.mydomain.com/' expected. Found element 'item' from namespace 'http://www.mydomain.com/'. Line 6, position 7. ---> System.Xml.XmlException: End element 'test' from namespace 'http://www.mydomain.com/' expected. Found element 'item' from namespace 'http://www.mydomain.com/'. Line 6, position 7.
   at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
   at System.Xml.XmlBaseReader.ReadEndElement()
   at System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.PartInfo.ReadValue(XmlDictionaryReader reader)
   at System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.DeserializeParameters(XmlDictionaryReader reader, PartInfo[] parts, Object[] parameters)
   at System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.DeserializeRequest(XmlDictionaryReader reader, Object[] parameters)
   at System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.DeserializeRequest(Message message, Object[] parameters)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Dispatcher.PrimitiveOperationFormatter.DeserializeRequest(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpcamp; rpc)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpcamp; rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpcamp; rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpcamp; rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
  

Если вы добавляете XmlSerializerFormat атрибут в интерфейс сервиса, то исключение не генерируется, но результирующий массив пуст (я подозреваю, что он не распознает отдельные элементы массива должным образом).

Если вы добавите XmlArrayItem атрибут к параметру, это, похоже, ничего не изменит ( void Test([XmlArrayItem("item")] int[] test); в службе).

Я пробовал различные другие комбинации XmlSerializerFormat , XmlArrayItem и XmlArray , но безуспешно.

Что мне нужно сделать, чтобы это работало должным образом?

Ответ №1:

Вот ответ, надеюсь, он кому-нибудь пригодится:

 [CollectionDataContract(ItemName = "item", Namespace = "http://www.mydomain.com/")]
public class ClientArray<T> : List<T> {

}

void Test(ClientArray<int> test);
  

Комментарии:

1. У меня была эта проблема в прошлом. Сложно разобраться, если вы не знаете, что искать.

2. Спасибо, [CollectionDataContract] делает это. Это объясняется здесь msdn.microsoft.com/en-us/library/aa347850.aspx

3. Итак, вам нужно расширить список до пользовательского типа, чтобы заставить это работать?