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

时间:2011-10-13 14:33:35

标签: c# java wcf web-services

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

我已经创建了一个服务引用,我可以调用该服务。问题是所有响应对象的属性都为null。 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序列化类,发现它是名称空间问题。以下代码摘录来自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. 在反序列化之前从响应中剥离命名空间。
  3. 但是,我想找到一种方法,使这项工作没有解决方法。我似乎无法找到一种方法来使命名空间匹配。我尝试了各种不同的属性,但似乎没有什么区别。

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

1 个答案:

答案 0 :(得分:1)

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

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

希望这有帮助。