Вызвать метод SOAP с префиксами пространства имен - PullRequest
2 голосов
/ 20 декабря 2010

Клиент веб-службы My C # отправляет следующее мыльное сообщение веб-службе на основе Java:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getData>
<request>
<requestParameters xmlns="http://b...">
<equals>
...
</equals>
</requestParameters>
</request>
</getData>
</soap:Body>
</soap:Envelope> 

и веб-служба на основе Java возвращает ошибку:

500 Internal Server Error
...
Cannot find dispatch method for {}getData
...

Клиент, написанный на Java, который работает, отправляет следующее сообщение:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ns2:getData xmlns:ns2="http://a...">
<ns2:request>
<ns3:requestParameters xmlns:ns3="http://b...">
<ns3:equals>
...
</ns3:equals>
</ns3:requestParameters>
</ns2:request>
</ns2:getData>
</soap:Body>
</soap:Envelope> 

Есть ли в C # простой способ отправлять сообщения SOAP так же, как отправляет клиент Java: с префиксами пространства имен?

Ниже приведен код C #, который отправляет сообщение:

// class MyService is auto-generated using wsdl.exe tool
MyService service = new MyService();

RequestMessage request = new RequestMessage();
...

ResponseMessage response = service.getData(request);
...

UPDATE:

Вот класс RequestMessage:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://uri.etsi.org/02657/v1.5.1#/RetainedData")]
public partial class RequestMessage
{

    private byte[] requestPriorityField;

    private RequestConstraints requestParametersField;

    private string deliveryPointHIBField;

    private string maxHitsField;

    private NationalRequestParameters nationalRequestParametersField;

    private System.Xml.XmlElement anyField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="hexBinary", Order=0)]
    public byte[] requestPriority
    {
        get
        {
            return this.requestPriorityField;
        }
        set
        {
            this.requestPriorityField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=1)]
    public RequestConstraints requestParameters
    {
        get
        {
            return this.requestParametersField;
        }
        set
        {
            this.requestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=2)]
    public string deliveryPointHIB
    {
        get
        {
            return this.deliveryPointHIBField;
        }
        set
        {
            this.deliveryPointHIBField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=3)]
    public string maxHits
    {
        get
        {
            return this.maxHitsField;
        }
        set
        {
            this.maxHitsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=4)]
    public NationalRequestParameters nationalRequestParameters
    {
        get
        {
            return this.nationalRequestParametersField;
        }
        set
        {
            this.nationalRequestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
    public System.Xml.XmlElement Any
    {
        get
        {
            return this.anyField;
        }
        set
        {
            this.anyField = value;
        }
    }
}

ОБНОВЛЕНИЕ № 2:

Причиной, по которой веб-службе на основе Java не понравился мой клиент C #, создаваемый SOAP-сообщение, является не пропуск префиксов пространства имен, а только из-за пропуска xmlns в элементе getData, поэтому, если мое сообщение выглядит так:

...
<getData xmlns="http://a...">
...
</getData>
...

это работает!

Мне удалось поместить xmlns в getData, вручную отредактировав SoapRpcMethodAttribute в исходном коде, созданном wsdl.exe. Вот выдержка:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
    Name="AxxxPortTypeBinding", Namespace="http://a...")]
public partial class AxxxService 
    : System.Web.Services.Protocols.SoapHttpClientProtocol {

    ...

    /// <remarks/>
    [System.Web.Services.Protocols.SoapRpcMethodAttribute(
        "http://a.../getData", 
        RequestNamespace = "http://a...", 
        ResponseNamespace = "http://a...",
        Use = System.Web.Services.Description.SoapBindingUse.Literal)]
    [return: System.Xml.Serialization.XmlElementAttribute("response")]
    public ResponseMessage getData(RequestMessage request) {
        object[] results = this.Invoke("getData", new object[] {
                    request});
        return ((ResponseMessage)(results[0]));
    }

    ...
}

До моего изменения SoapRpcMethodAttribute имел следующий конструктор:

[System.Web.Services.Protocols.SoapRpcMethodAttribute(
    "", RequestNamespace = "", ResponseNamespace = "",
    Use = System.Web.Services.Description.SoapBindingUse.Literal)]

Теперь возникает вопрос: что поместить в файл WSDL, чтобы SoapRpcMethodAttribute содержал эти строки в конструкторе (заполненном инструментом wsdl.exe)?

Ответы [ 3 ]

1 голос
/ 20 декабря 2010

Я сталкивался с этой проблемой раньше, когда утилита WSDL.exe неправильно выдвигала пространство имен при генерации кода сервиса. Проверьте определение объекта request в сгенерированном коде. Я предполагаю, что в определении класса для объекта request не определен атрибут XmlRootAttribute.

Добавление атрибута [XmlRootAttribute(Namespace "http://a...")] к определению класса для объекта request должно решить эту проблему.

В качестве примечания я рекомендую добавить этот дополнительный атрибут в отдельный файл кода, используя частичное определение класса. Определение атрибута в отдельном файле позволит вам при необходимости перегенерировать код веб-службы, используя WSDL.exe, не перезаписывая исправление для правильной установки пространства имен корневого элемента.

0 голосов
/ 20 мая 2016

У меня возникла та же проблема, и я решил ее, изменив значение свойства Использование в System.Web.Services.Protocols.SoapDocumentMethodAttribute атрибут, соответствующий каждому методу веб-службы. System.Web.Services.Description.SoapBindingUse. Литеральное значение по умолчанию заменено на System.Web.Services.Description.SoapBindingUse. Кодировано .

0 голосов
/ 21 декабря 2010

В сгенерированном прокси-классе должно быть правильное пространство имен. Я рекомендую две вещи:

1) Запустите WSDL.EXE из командной строки и обратите внимание на наличие ошибок или предупреждений. Если да, то отредактируйте свой вопрос, чтобы включить их.

2) Если вы не застряли с использованием .NET 2.0, вы должны попытаться создать прокси-классы, используя «Добавить ссылку на службу» или эквивалентный «SVCUTIL.EXE», они будут использовать современную инфраструктуру WCF на стороне клиента который, скорее всего, был исправлен для решения этой проблемы.

...