繁体   English   中英

WCF客户端/ Java Web服务 - 反序列化的对象为空

[英]WCF client / Java Web Service - deserialized objects are null

我正在尝试将Java Web服务集成到我的C#项目中。 Web服务由我公司的另一个部门维护,不受我的控制。

我已经创建了一个服务引用,我可以调用该服务。 问题是所有响应对象的属性都为null。 SOAP响应从服务器返回,但没有正确反序列化。 没有报告或记录错误。

这似乎是一个相当普遍的问题,常见的答案是命名空间不匹配。 我相信这也是我的问题,但我无法纠正它。

Web服务是私有的。 我试图整理一个说明问题的样本。 这是相关的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序列化类,发现它是命名空间问题。 以下代码摘录来自deserialzer:

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>

我有解决方法:

  1. 创建和维护自定义序列化程序。
  2. 在反序列化之前从响应中剥离名称空间。

但是,我想找到一种方法,使这项工作没有解决方法。 我似乎无法找到一种方法来使命名空间匹配。 我尝试了各种不同的属性,但似乎没有什么区别。

我还没有发布WSDL。 这是一项私人服务,我无法对其进行任何更改。 如果您需要查看WSDL,请告诉我,我会看到我能做些什么。

很可能WSDL没有具有正确名称空间的CallSuccessful和CallErrorMessage标记,这就是您的服务代理类没有适当名称空间的原因。

您可以实际下载WSDL,将其保存在项目中,根据需要处理命名空间,从此WSDL生成服务引用(通过使用GUI向导或svcutil),将app.config或web.config文件指向实际的java web服务。 每次需要更新服务时,都可以按照此过程进行操作。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM