2

私は次のようなXML文字列を持っています

<?xml version="1.0"?>
<FullServiceAddressCorrectionDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <AuthenticationInfo xmlns="http://www.usps.com/postalone/services/UserAuthenticationSchema">
    <UserId xmlns="">FAPushService</UserId>
    <UserPassword xmlns="">Password4Now</UserPassword>
  </AuthenticationInfo>
</FullServiceAddressCorrectionDelivery>

クラスでノードをマップするために、私はWCFのようなクラス構造を持っています

[DataContract]
[Serializable]
public class FullServiceAddressCorrectionDelivery
{
    [XmlElement("AuthenticationInfo", Namespace = "http://www.usps.com/postalone/services/UserAuthenticationSchema")]
    [DataMember]
    public AuthenticationInfo AuthenticationInfo { get; set; }
}

[DataContract]
[Serializable]
public class AuthenticationInfo
{
    [DataMember]
    [XmlElement("UserId", Namespace = "")]
    public string UserId { get; set; }

    [DataMember]
    [XmlElement("UserPassword", Namespace = "")]
    public string UserPassword { get; set; }
}

De-serialization の場合、xmlserializer を使用してオブジェクトを逆シリアル化しました

XmlSerializer xs = new XmlSerializer(typeof(FullServiceAddressCorrectionDelivery));
var result = (FullServiceAddressCorrectionDelivery)xs.Deserialize(stream);

このメソッドは Null FullServiceAddressCorrectionDelivery オブジェクトを返しました..しかし、DataContractSerializer を使用したとき..のように

DataContractSerializer xs = new DataContractSerializer(typeof(FullServiceAddressCorrectionDelivery));
var result = (FullServiceAddressCorrectionDelivery)xs.ReadObject(stream);

その後、次の例外が出てきました..

行 2 の位置 46 にエラーがあります。名前空間 'http://schemas.datacontract.org/2004/07/WcfService1' から要素 'FullServiceAddressCorrectionDelivery' を予期しています。

私はこれで立ち往生しています...クラスが同じプロジェクトにある場合、RENE(StackOverFlowメンバー)の助けを借りて逆シリアル化に成功しました..しかし、それらをWCF Datacontractsに変換すると..その問題に遭遇しました..ここで私が間違っているところを教えてください...

4

1 に答える 1

1

その入力に対してデータ コントラクト シリアライザー (DCS) をどのように使用するかによって、それができる場合とできない場合があります。DCSのデータ メンバーの名前空間は、それがルート要素でない限り、それらが属するコントラクトの名前空間によって定義されます (この場合、[DC] 名前空間は要素の名前空間も定義します)。

ルート要素である FullServiceAddressCorrectionDelivery には、サンプル XML (空) に 1 つの名前空間があり、そのメンバーである AuthenticationInfo には別の名前空間 (http://www.usps.com/postalone...) があります。つまり、シリアライザーの作成方法を実際に変更しない限り、この型に DCS を使用することはできません。

ただし、XmlSerializer (XS) は問題なく動作するはずです。型のメンバーは異なる名前空間を持つことができます。以下のコードでわかるように、入力として FullServiceAddressCorrectionDelivery を受け取る操作に、提供された XML を逐語的に投稿できます。オブジェクトは適切に設定されています。[XmlSerializerFormat で操作 (またはコントラクト) をマークする必要があります。 ] 属性を使用してこの動作を取得します。

public class Post_6fc3a1bd_b3ca_48da_b4d2_35271135ed8a
{
    const string XML = @"<?xml version=""1.0""?>
 <FullServiceAddressCorrectionDelivery xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
 xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
   <AuthenticationInfo xmlns=""http://www.usps.com/postalone/services/UserAuthenticationSchema"">
     <UserId xmlns="""">FAPushService</UserId>
     <UserPassword xmlns="""">Password4Now</UserPassword>
   </AuthenticationInfo>
 </FullServiceAddressCorrectionDelivery>";

    [XmlRoot(ElementName = "FullServiceAddressCorrectionDelivery", Namespace = "")]
    public class FullServiceAddressCorrectionDelivery
    {
        [XmlElement("AuthenticationInfo", Namespace = "http://www.usps.com/postalone/services/UserAuthenticationSchema")]
        [DataMember]
        public AuthenticationInfo AuthenticationInfo { get; set; }
    }

    public class AuthenticationInfo
    {
        [XmlElement("UserId", Namespace = "")]
        public string UserId { get; set; }

        [XmlElement("UserPassword", Namespace = "")]
        public string UserPassword { get; set; }
    }

    [ServiceContract(Namespace = "")]
    public interface ITest
    {
        [XmlSerializerFormat]
        [OperationContract]
        FullServiceAddressCorrectionDelivery Echo(FullServiceAddressCorrectionDelivery input);
    }

    public class Service : ITest
    {
        public FullServiceAddressCorrectionDelivery Echo(FullServiceAddressCorrectionDelivery input)
        {
            return input;
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "text/xml";
        Console.WriteLine(c.UploadString(baseAddress + "/Echo", XML));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

完全を期すために、シリアライザーの作成 (ルート名と名前空間を渡す) を変更して、データ コントラクト シリアライザーを使用して提供した XML を逆シリアル化できるようにする方法を次に示します。

public class Post_6fc3a1bd_b3ca_48da_b4d2_35271135ed8a_b
{
    const string XML = @"<?xml version=""1.0""?>
 <FullServiceAddressCorrectionDelivery xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
 xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
   <AuthenticationInfo xmlns=""http://www.usps.com/postalone/services/UserAuthenticationSchema"">
     <UserId xmlns="""">FAPushService</UserId>
     <UserPassword xmlns="""">Password4Now</UserPassword>
   </AuthenticationInfo>
 </FullServiceAddressCorrectionDelivery>";

    [DataContract(Name = "FullServiceAddressCorrectionDelivery", Namespace = "http://www.usps.com/postalone/services/UserAuthenticationSchema")]
    public class FullServiceAddressCorrectionDelivery
    {
        [DataMember]
        public AuthenticationInfo AuthenticationInfo { get; set; }
    }

    [DataContract(Name = "AuthenticationInfo", Namespace = "")]
    public class AuthenticationInfo
    {
        [DataMember]
        public string UserId { get; set; }

        [DataMember]
        public string UserPassword { get; set; }
    }

    static string Serialize(object obj, bool useDataContractSerializer)
    {
        MemoryStream ms = new MemoryStream();
        XmlWriterSettings ws = new XmlWriterSettings
        {
            Indent = true,
            IndentChars = "  ",
            OmitXmlDeclaration = false,
            Encoding = new UTF8Encoding(false)
        };
        XmlWriter w = XmlWriter.Create(ms, ws);
        if (useDataContractSerializer)
        {
            var dcs = new DataContractSerializer(obj.GetType(), "FullServiceAddressCorrectionDelivery", "");
            dcs.WriteObject(w, obj);
        }
        else
        {
            new XmlSerializer(obj.GetType()).Serialize(w, obj);
        }

        w.Flush();
        string result = Encoding.UTF8.GetString(ms.ToArray());
        Console.WriteLine(result);

        w.Close();
        ms.Close();
        return result;
    }

    public static void Test()
    {
        Console.WriteLine("Serialization:");
        MemoryStream ms = new MemoryStream();
        XmlWriterSettings ws = new XmlWriterSettings
        {
            Indent = true,
            IndentChars = "  ",
            OmitXmlDeclaration = false,
            Encoding = new UTF8Encoding(false)
        };
        XmlWriter w = XmlWriter.Create(ms, ws);
        var dcs = new DataContractSerializer(typeof(FullServiceAddressCorrectionDelivery), "FullServiceAddressCorrectionDelivery", "");

        var obj = new FullServiceAddressCorrectionDelivery
        {
            AuthenticationInfo = new AuthenticationInfo
            {
                UserId = "FAPushService",
                UserPassword = "Password4Now"
            }
        };

        dcs.WriteObject(w, obj);

        w.Flush();
        string result = Encoding.UTF8.GetString(ms.ToArray());
        Console.WriteLine(result);
        Console.WriteLine();

        Console.WriteLine("Deserialization:");
        ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));

        var obj2 = (FullServiceAddressCorrectionDelivery)dcs.ReadObject(ms);
        Console.WriteLine("{0} - {1}", obj2.AuthenticationInfo.UserId, obj2.AuthenticationInfo.UserPassword);
    }
}
于 2012-06-04T20:05:20.040 に答える