Проблемы с сериализацией .NET WCF - PullRequest
5 голосов
/ 20 апреля 2011

Ситуация: система A должна предоставлять веб-сервис SOAP 1.2 для вызова системой B.Чтобы A знал, как выглядит сообщение, B отправил XSD A, описывающий содержимое сообщения.Сгенерировал заглушки с помощью инструмента .NET xsd.exe, создал простой веб-сервис для этого и работа была выполнена.

Однако;когда B вызывает этот веб-сервис, A отказывается сериализовать содержимое SOAP / XML для созданных экземпляров прокси-класса.Я понимаю, что это должно быть связано с тем, как сериализация определена на стороне веб-службы в системе A, но не смогла точно определить, что происходит.

Как выглядит сообщение от B (анонимный) - СБОЙ:

<ns2:Set_Out xmlns:ns2="http://a.a/1.0" xmlns:ns1="http://b.b/1.0" xmlns:ns0="http://c.c">
<Context xmlns="">
    <Foo>test</Foo>
    <Bar>test</Bar>
    ...
</Context>

Как выглядит тестовое сообщение от тестового клиента (на основе WSDL) - РАБОТЫ:

<Set_Out xmlns="http://a.a/1.0">
<Context xmlns:b="http://schemas.datacontract.org/2004/07/x.x" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <b:Foo>TEST</b:Foo>
    <b:Bar>test</b:Bar>
    ...
</Context>

Когда веб-сервис, созданный A, получает сообщения от B, он вообще не сериализует сообщение.Объектами прокси (например, Context) являются null.Когда он получает сообщения от тестового клиента, все генерируется правильно.

Атрибуты сериализации на прокси:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://a.a/1.0")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://a.a/1.0", IsNullable=false)]
[System.ServiceModel.MessageContract]
public partial class Set_Out {
    [System.Xml.Serialization.XmlElementAttribute(Namespace="http://a.a/1.0", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]    [System.ServiceModel.MessageBodyMember(Order=0)]
    public ContextType Context;
    ...

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://a.a/1.0")]
public partial class ContextType {
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string Foo;

Вещи, которые я нахожу странными:

  1. При создании WSDL для этой службы WSDL добавляет свои собственные пространства имен к определению WSDL (например, xmlns:b в приведенном выше примере).
  2. WSDL не уважаетunqualified аннотации, определенные в прокси-сервере и делающие все квалифицированными.

Я пробовал различные комбинации аннотаций, но, похоже, ничего не помогло;сообщения от B неправильно десериализованы в прокси, сгенерированные A. Любые идеи / указатели / помощь будут высоко оценены!

Ответы [ 2 ]

5 голосов
/ 20 апреля 2011

В типичном случае «задайте вопрос, решите его самостоятельно через 5 минут», мне удалось решить мою проблему.

Проблема заключалась в том, что, по-видимому, при использовании WCF .NET использует сериализатор по умолчанию для классов, участвующих в контракте данных. Этот сериализатор по умолчанию (я полагаю, что он DataContractSerializer), по-видимому, на самом деле не позволяет многое сделать в конфигурации. Я должен был сказать WCF использовать XmlSerializer для сериализации сообщения. Для этого мне пришлось добавить аннотацию [XmlSerializerFormat()] в интерфейс контракта на обслуживание (по-видимому, он также предназначен для работы). Пример:

[ServiceContract(Namespace = "http://a.a/1.0")]
[XmlSerializerFormat()]
public interface IMyWebService
{
    [OperationContract()]
    void DoStuff(Set_Out message);
}

После добавления аннотации [XmlSerializerFormat()] WSDL значительно изменился (правильные пространства имен) и сообщения сериализованы правильно.

Пост форума, который поставил меня на правильный путь: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c7fede29-56c2-4ff3-bd02-48e3e0b2cec1/

2 голосов
/ 20 апреля 2011

(на самом деле это комментарий, но он не подходит)

Попробуйте добавить system.diagnostics в ваш web.config, чтобы узнать больше информации об ошибках:

    <system.diagnostics>
    <trace autoflush="true" />
    <sources>
        <source name="System.ServiceModel"
                switchValue="Information, ActivityTracing"
                propagateActivity="true">
            <listeners>
                <add name="sdt"
                    type="System.Diagnostics.XmlWriterTraceListener"
                    initializeData= "C:\MyLog.svclog" />
            </listeners>
        </source>
    </sources>
    </system.diagnostics>

Вы можете просмотреть svclog, используя C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe (или аналогичный). Добавьте это к обеим службам (конечно же, к разным именам журналов) и посмотрите, какая из них дает сбой и почему.

Я подозреваю, что с сериализацией все в порядке, но некоторая привязка / настройка службы вызывает сбой вызова.

...