Java序列化与.NET序列化

未付帐单

我们正在合作的Java商店供应商需要我们(.NET商店)提供符合他们发送给我们的WSDL的RESTful服务。我们返回的XML与供应商的期望之间存在一些差异。我的过程从根本上是错误的,还是Java和.NET进行序列化的方式只是不同?

我的过程:

该合同第一个想法是新的给我,但在这样的职位上覆盖好这个因此,只要具备一点知识,我就可以通过SvcUtil.exe运行WSDL和关联的.XSD来生成C#(下面的一些相关摘录),并且我将这些类型用作服务的返回类型。

我也尝试过使用wsdl.exe生成代码xsd.exe,但是都没有明显改变结果。

区别:

  1. 其他级别出现在我的XML中。在我的系统中,有时会存在一个与属性名称相对应的XML实体(例如“ Code”),并且在其内部有一个与属性类型相对应的XML元素(例如“ CodeType”)。供应商只期望一个级别:“代码”。
  2. 命名空间是不同的。
  3. 供应商期望的属性(“ codeValue”)作为元素出现。
  4. Null属性包含在我的XML中。

结果和代码摘录:

供应商希望该服务返回如下所示的消息:

<?xml version="1.0" encoding="UTF-8"?>
<gms:GetClassificationResponse xmlns:gms="http://vendor.com/metadata/cms/services/integration/gms" xmlns:class="http://vendor.com/metadata/model/classification" xmlns:core="http://vendor.com/metadata/model/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://vendor.com/metadata/cms/services/integration/gms ../gms_services.xsd">
  <class:ClassificationVersion>
    <class:Code codeValue="01">
      <Name core:type="Preferred">Northland Region</Name>
      <class:Code codeValue="001">
        <Name core:type="Preferred">Far North District</Name>
        <class:Code codeValue="500206">
          <Name core:type="Preferred">North Cape</Name>
        </class:Code>
        <class:Code codeValue="500207">
          <Name core:type="Preferred">Houhora</Name>
        </class:Code>
        <!-- Truncated -->
      </class:Code>
      <class:Code codeValue="002">
        <Name core:type="Preferred">Whangarei District</Name>
        <!-- Children omitted -->
      </class:Code>
      <!-- Truncated -->
    </class:Code>
    <class:Code codeValue="02">
      <Name core:type="Preferred">Auckland Region</Name>
      <!-- Children omitted -->
    </class:Code>
    <!-- Truncated -->
  </class:ClassificationVersion>
</gms:GetClassificationResponse>

我们正在产生这样的结果:

<GetClassificationResponseType xmlns="http://schemas.datacontract.org/2004/07/metadata.cms.services.integration.gms" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ClassificationVersion>
    <actionField>ADD</actionField>
    <actionFieldSpecified>false</actionFieldSpecified>
    <anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
    <descriptionField i:nil="true"/>
    <detailField>full</detailField>
    <idField i:nil="true"/>
    <itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
    <lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
    <lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
    <nameField i:nil="true"/>
    <uriField i:nil="true"/>
    <isPreferredField>false</isPreferredField>
    <itemField i:nil="true"/>
    <validFromField>0001-01-01T00:00:00</validFromField>
    <validFromFieldSpecified>false</validFromFieldSpecified>
    <validToField>0001-01-01T00:00:00</validToField>
    <validToFieldSpecified>false</validToFieldSpecified>
    <Code>
      <CodeType>
        <actionField>ADD</actionField>
        <actionFieldSpecified>false</actionFieldSpecified>
        <anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
        <descriptionField i:nil="true"/>
        <detailField>full</detailField>
        <idField>Whangarei</idField>
        <itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
        <lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
        <lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
        <nameField>
          <ContextualStringType>
            <anyField/>
            <isStructuredField>true</isStructuredField>
            <actionField>ADD</actionField>
            <actionFieldSpecified>false</actionFieldSpecified>
            <anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
            <langField i:nil="true"/>
            <typeField>Preferred</typeField>
          </ContextualStringType>
        </nameField>
        <uriField i:nil="true"/>
        <Code>
          <CodeType>
            <actionField>ADD</actionField>
            <actionFieldSpecified>false</actionFieldSpecified>
            <anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
            <descriptionField i:nil="true"/>
            <detailField>full</detailField>
            <idField>Springs Flat</idField>
            <itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
            <lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
            <lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
            <nameField>
              <ContextualStringType>
                <anyField/>
                <isStructuredField>true</isStructuredField>
                <actionField>ADD</actionField>
                <actionFieldSpecified>false</actionFieldSpecified>
                <anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
                <langField i:nil="true"/>
                <typeField>Preferred</typeField>
              </ContextualStringType>
            </nameField>
            <uriField i:nil="true"/>
            <Code/>
            <category i:nil="true"/>
            <codeValue>502001</codeValue>
            <level xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
          </CodeType>

还有一些生成的代码

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://mtna.us/metadata/cms/services/integration/gms")]
[DataContract]
public partial class GetClassificationResponseType
{
    private ClassificationVersionType classificationVersionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "http://mtna.us/metadata/model/classification", Order = 0)]
    [DataMember]
    public ClassificationVersionType ClassificationVersion
    {
        get
        {
            return this.classificationVersionField;
        }
        set
        {
            this.classificationVersionField = value;
        }
    }
}

...

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://vendor.com/metadata/model/classification")]
public partial class ClassificationVersionType : ObjectVersionType
{

    private LevelType1[] levelField;

    private CodeType[] codeField;

    private bool isViewField;

    private string basisField;

    public ClassificationVersionType()
    {
        this.isViewField = false;
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Level", Order = 0)]
    public LevelType1[] Level
    {
        get
        {
            return this.levelField;
        }
        set
        {
            this.levelField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Code", Order = 1)]
    public CodeType[] Code
    {
        get
        {
            return this.codeField;
        }
        set
        {
            this.codeField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    [System.ComponentModel.DefaultValueAttribute(false)]
    public bool isView
    {
        get
        {
            return this.isViewField;
        }
        set
        {
            this.isViewField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")]
    public string basis
    {
        get
        {
            return this.basisField;
        }
        set
        {
            this.basisField = value;
        }
    }
}
未付帐单

在供应商的大量帮助下,我们最终使这项工作奏效。从那以后,我离开了组织-但我保留了代码的副本。

我们使用了它-https://msdn.microsoft.com/zh-cn/library/aa395223(v=vs.110).aspx-我们的完整实现如下。

我们用以下内容装饰了服务接口DispatchByBodyElementBehavior

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[ServiceContract(Namespace = "http://vendor.com/project/wsdl"), XmlSerializerFormat, DispatchByBodyElementBehavior]
public interface IContractFirstService

我们还必须修改SvcUtil.exe生成的代码,但不能进行大量修改。只有几个地方需要调整。与数组限制有关。对不起,我不记得了。我很确定从编译/运行时错误中可以做什么是很明显的。

这是我们的实现方式DispatchByBodyElementBehavior

using System;
using System.Diagnostics;
using System.ServiceModel.Channels;
using System.Collections.Generic;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml;

/*
 * This code was written based on the sample provided at http://msdn.microsoft.com/en-us/library/aa395223(v=vs.110).aspx. 
 * The purpose of this is to allow dispatching of the incoming SOAP requests based on the payload XML element. 
 * This allows the more standard document/literal service contract design to be used and does not rely on SOAP actions. 
 */
namespace OurOrganisation.Services.VendorIntegrationServices
{
    class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
    {
        Dictionary<XmlQualifiedName, string> dispatchDictionary;
        string defaultOperationName;

        public DispatchByBodyElementOperationSelector(Dictionary<XmlQualifiedName, string> dispatchDictionary, string defaultOperationName)
        {
            try
            {
                this.dispatchDictionary = dispatchDictionary;
                this.defaultOperationName = defaultOperationName;
            }
            catch (Exception ex)
            {
                Logger.Write(ex.Message);
                throw;
            }
        }

        #region IDispatchOperationSelector Members

        private Message CreateMessageCopy(Message message, XmlDictionaryReader body)
        {
            Message copy = Message.CreateMessage(message.Version, message.Headers.Action, body);
            copy.Headers.CopyHeaderFrom(message, 0);
            copy.Properties.CopyProperties(message.Properties);
            return copy;
        }

        public string SelectOperation(ref System.ServiceModel.Channels.Message message)
        {
            try
            {
                XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
                XmlQualifiedName lookupQName = new XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);
                message = CreateMessageCopy(message, bodyReader);
                if (dispatchDictionary.ContainsKey(lookupQName))
                {
                    return dispatchDictionary[lookupQName];
                }
                else
                {
                    return defaultOperationName;
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex.Message);
                throw;
            }

        }

        #endregion
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
    sealed class DispatchByBodyElementBehaviorAttribute : Attribute, IContractBehavior
    {
        #region IContractBehavior Members

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            // no binding parameters need to be set here
            return;
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            // this is a dispatch-side behavior which doesn't require
            // any action on the client
            return;
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
        {
            // We iterate over the operation descriptions in the contract and
            // try to locate an DispatchBodyElementAttribute behaviors on each 
            // operation. If found, we add the operation, keyed by QName of the body element 
            // that selects which calls shall be dispatched to this operation to a 
            // dictionary. 

            //Logger.Write("starting ApplyDispatchBehavior");

            try
            {
                Dictionary<XmlQualifiedName, string> dispatchDictionary = new Dictionary<XmlQualifiedName, string>();
                foreach (OperationDescription operationDescription in contractDescription.Operations)
                {
                    DispatchBodyElementAttribute dispatchBodyElement =
                        operationDescription.Behaviors.Find<DispatchBodyElementAttribute>();
                    if (dispatchBodyElement != null)
                    {
                        dispatchDictionary.Add(dispatchBodyElement.QName, operationDescription.Name);
                        //Logger.Write(string.Format("method {0} added", operationDescription.Name));
                    }
                }

                // Lastly, we create and assign and instance of our operation selector that
                // gets the dispatch dictionary we've just created.
                dispatchRuntime.OperationSelector =
                    new DispatchByBodyElementOperationSelector(
                        dispatchDictionary,
                        dispatchRuntime.UnhandledDispatchOperation.Name);
            }
            catch(Exception ex)
            {
                Logger.Write(ex.Message);
                throw;
            }
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
            // 
        }

        #endregion
    }

    [AttributeUsage(AttributeTargets.Method)]
    sealed class DispatchBodyElementAttribute : Attribute, IOperationBehavior
    {
        XmlQualifiedName qname;

        public DispatchBodyElementAttribute(string name)
        {
            qname = new XmlQualifiedName(name);
        }

        public DispatchBodyElementAttribute(string name, string ns)
        {
            qname = new XmlQualifiedName(name, ns);
        }

        internal XmlQualifiedName QName
        {
            get { return qname; }
            set { qname = value; }
        }


        #region IOperationBehavior Members

        public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
        {

        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
        {

        }

        public void Validate(OperationDescription operationDescription)
        {
        }

        #endregion
    }

    internal class Logger
    {
        public static void Write(string message)
        {
            string sSource;
            string sLog;
            string sEvent;

            sSource = "MAL dispatch by body extension";
            sLog = "Application";
            sEvent = message;

            if (!EventLog.SourceExists(sSource))
                EventLog.CreateEventSource(sSource, sLog);

            EventLog.WriteEntry(sSource, sEvent);
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章