Я пытаюсь интегрировать веб-сервис Java в мой проект C #.Веб-служба обслуживается другим подразделением моей компании и находится вне моего контроля.
Я создал ссылку на службу и могу позвонить в службу.Проблема в том, что все свойства объекта ответа являются нулевыми.Ответ SOAP возвращается с сервера, но не десериализован должным образом.Об ошибках или сообщениях об этом не сообщается.
Похоже, что это довольно распространенная проблема, и общий ответ - несоответствие пространства имен.Я тоже считаю, что это моя проблема, но у меня проблемы с ее исправлением.
Веб-служба является частной.Я попытался собрать образец, который иллюстрирует проблему.Вот соответствующий код Reference.cs:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "www.namespace1.com", ConfigurationName = "MyService.MyServiceClient")]
public interface MyServiceClient
{
[System.ServiceModel.OperationContractAttribute(Action = "", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults = true, Use = System.ServiceModel.OperationFormatUse.Encoded)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(MyOperationResponseType))]
myOperationResponse myOperation(myOperationRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = "www.namespace2.com")]
public partial class MyOperationResponseType : object, System.ComponentModel.INotifyPropertyChanged
{
private bool callSuccessfulField;
private string callErrorMessageField;
/// <remarks/>
public bool CallSuccessful
{
get
{
return this.callSuccessfulField;
}
set
{
this.callSuccessfulField = value;
this.RaisePropertyChanged("CallSuccessful");
}
}
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable = true)]
public string CallErrorMessage
{
get
{
return this.callErrorMessageField;
}
set
{
this.callErrorMessageField = value;
this.RaisePropertyChanged("CallErrorMessage");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null))
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName = "myOperationResponse", WrapperNamespace="www.namespace1.com", IsWrapped = true)]
public partial class myOperationResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "", Order = 0)]
public MyOperationResponseType result;
public myOperationResponse()
{
}
public myOperationResponse(MyOperationResponseType result)
{
this.result = result;
}
}
Ответ SOAP, который я получаю, выглядит следующим образом:
<env:Envelope env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<m:myOperationResponse xmlns:m="www.namespace1.com">
<result>
<ns2:CallSuccessful xmlns:ns2="www.namespace2.com">false</ns2:CallSuccessful>
<ns2:CallErrorMessage xmlns:ns2="www.namespace2.com">Failed for some reason.</ns2:CallErrorMessage>
</result>
</m:myOperationResponse>
</env:Body>
</env:Envelope>
Экземпляр MyOperationResponseType создается, но CallErrorMessage и CallSuccessfulполя не заполнены.
Я использовал SGEN для генерации классов сериализации XML и обнаружил, что это проблема пространства имен.Следующие отрывки кода взяты из десериализатора:
string id2_Item;
id2_Item = Reader.NameTable.Add(@"");
global::MyOperationResponseType o;
o = new global::MyOperationResponseType();
if (!paramsRead[1] && ((object) Reader.LocalName == (object)id158_CallSuccessful && (object) Reader.NamespaceURI == (object)id2_Item)) {
{
o.@CallSuccessful = System.Xml.XmlConvert.ToBoolean(Reader.ReadElementString());
}
paramsRead[1] = true;
}
Условное условие не выполняется, поскольку Reader.NamespaceURI = "www.namespace2.com"
и id2_Item = ""
Если я вручную установлю id2_Item = "www.namespace2.com"
, то десериализация будет работать.
Кроме того, если я удаляю пространства имен из ответа SOAP, он будет работать:
<env:Envelope env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<m:myOperationResponse xmlns:m="www.namespace1.com">
<result>
<CallSuccessful>false</CallSuccessful>
<CallErrorMessage>Failed for some reason.</CallErrorMessage>
</result>
</m:myOperationResponse>
</env:Body>
У меня есть обходные пути:
- Создание и поддержка собственного сериализатора.
- Извлечение пространства имен из ответа до десериализации.
Однако я хотел бы найти способ сделать эту работу без обходных путей.Я просто не могу найти способ привести пространства имен в соответствие.Я пробовал множество различных атрибутов, но, похоже, ничего не изменит.
Я не опубликовал WSDL.Это частный сервис, и я не могу внести в него какие-либо изменения.Если вам нужно посмотреть WSDL, дайте мне знать, и я посмотрю, что я могу сделать.