【问题标题】:Deserialize Nested XML with Web Api MVC 4使用 Web Api MVC 4 反序列化嵌套 XML
【发布时间】:2015-03-05 01:41:22
【问题描述】:

我有以下 XML,我试图将其反序列化为带有 .Net Framework 4.5 的 MVC 4 Web Api 的订单对象...但是当我使用 POST 从 Chrome Advanced Rest Client 发送此 XML 并将 Content-Type 设置为application/xml 服务器上的订单数据为空(如果我发送由 Web Api 帮助页面生成的示例 xml,它似乎确实有效)。如何在不更改的情况下反序列化原始 xml?

<?xml version="1.0" encoding="utf-8" ?>
    <order>
    <header>
        <organization id="1"></organization>
        <customerClient id=""></customerClient>
        <date>05/06/14</date>
        <customerOrderNumber>123-4567-8901</customerOrderNumber>
        <number>abc-1234</number>
                <OriginalNumber></OriginalNumber>
                <status id="0"></status>
        <billing-info>
            <name>A Person</name>
            <address1>123 Main Street</address1>
            <address2></address2>
            <city>Cityville</city>
            <state>AK</state>
            <zip>55555</zip>
            <country>US</country>
            <phone>5555551212</phone>
            <emailAddress>aperson@gmail.com</emailAddress>
            <cc number="" exp="" ccv="" amt=""></cc>
        </billing-info>
    </header>
    <data>
        <shipments>
            <shipment>
                <shipping-info>
                    <name>A Person</name>
                    <address1>123 Main Street</address1>
                    <address2></address2>
                    <city>Cityville</city>
                    <state>AK</state>
                    <zip>55555</zip>
                    <country>US</country>
                    <phone></phone>
                    <emailAddress>aperson@gmail.com</emailAddress>
                    <method>13</method>
                    <shipCharge>2.00</shipCharge>
                </shipping-info>
                <gift-note></gift-note>
                <ship-attributes></ship-attributes>
                <products>
                    <line-item number="1">
                        <mc_order></mc_order>
                        <sku>ABC123</sku>
                        <quantity>1</quantity>
                        <description></description>
                        <images>
                            <image no="1">
                                <url>http://pictures.com/123/page1.jpg</url>
                            </image>
                            <image no="2">
                                <url>http://pictures.com/123/page1.jpg</url>
                            </image>
                        </images>
                        <attributes>
                            <attribute id="123"></attribute>
                        </attributes>
                    </line-item>
                </products>
            </shipment>
        </shipments>
    </data>
</order>

XML 模式是一成不变的,我不允许修改它。

我已将 XML As Classes 粘贴到 Visual Studio 2012 中的 Web Api 项目中,它创建了这个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Serialization;

namespace MyProject.Models
{

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class order
    {

        private orderHeader headerField;

        private orderData dataField;

        /// <remarks/>
        public orderHeader header
        {
            get
            {
                return this.headerField;
            }
            set
            {
                this.headerField = value;
            }
        }

        /// <remarks/>
        public orderData data
        {
            get
            {
                return this.dataField;
            }
            set
            {
                this.dataField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class orderHeader
    {

        private orderHeaderOrganization organizationField;

        private orderHeaderCustomerClient customerClientField;

        private string dateField;

        private string customerOrderNumberField;

        private string numberField;

        private object originalNumberField;

        private orderHeaderStatus statusField;

        private orderHeaderBillinginfo billinginfoField;

        /// <remarks/>
        public orderHeaderOrganization organization
        {
            get
            {
                return this.organizationField;
            }
            set
            {
                this.organizationField = value;
            }
        }

        /// <remarks/>
        public orderHeaderCustomerClient customerClient
        {
            get
            {
                return this.customerClientField;
            }
            set
            {
                this.customerClientField = value;
            }
        }

        /// <remarks/>
        public string date
        {
            get
            {
                return this.dateField;
            }
            set
            {
                this.dateField = value;
            }
        }

        /// <remarks/>
        public string customerOrderNumber
        {
            get
            {
                return this.customerOrderNumberField;
            }
            set
            {
                this.customerOrderNumberField = value;
            }
        }

        /// <remarks/>
        public string number
        {
            get
            {
                return this.numberField;
            }
            set
            {
                this.numberField = value;
            }
        }

        /// <remarks/>
        public object OriginalNumber
        {
            get
            {
                return this.originalNumberField;
            }
            set
            {
                this.originalNumberField = value;
            }
        }

        /// <remarks/>
        public orderHeaderStatus status
        {
            get
            {
                return this.statusField;
            }
            set
            {
                this.statusField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("billing-info")]
        public orderHeaderBillinginfo billinginfo
        {
            get
            {
                return this.billinginfoField;
            }
            set
            {
                this.billinginfoField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class orderHeaderOrganization
    {

        private byte idField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public byte id
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class orderHeaderCustomerClient
    {

        private string idField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string id
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class orderHeaderStatus
    {

        private byte idField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public byte id
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class orderHeaderBillinginfo
    {

        private string nameField;

        private string address1Field;

        private object address2Field;

        private string cityField;

        private string stateField;

        private ushort zipField;

        private string countryField;

        private ulong phoneField;

        private string emailAddressField;

        private orderHeaderBillinginfoCC ccField;

        /// <remarks/>
        public string name
        {
            get
            {
                return this.nameField;
            }
            set
            {
                this.nameField = value;
            }
        }

        /// <remarks/>
        public string address1
        {
            get
            {
                return this.address1Field;
            }
            set
            {
                this.address1Field = value;
            }
        }

        /// <remarks/>
        public object address2
        {
            get
            {
                return this.address2Field;
            }
            set
            {
                this.address2Field = value;
            }
        }

        /// <remarks/>
        public string city
        {
            get
            {
                return this.cityField;
            }
            set
            {
                this.cityField = value;
            }
        }

        /// <remarks/>
        public string state
        {
            get
            {
                return this.stateField;
            }
            set
            {
                this.stateField = value;
            }
        }

        /// <remarks/>
        public ushort zip
        {
            get
            {
                return this.zipField;
            }
            set
            {
                this.zipField = value;
            }
        }

        /// <remarks/>
        public string country
        {
            get
            {
                return this.countryField;
            }
            set
            {
                this.countryField = value;
            }
        }...you get the idea, it's too long to post here.

Web Api 帮助页面显示了一个可接受的 XML 输入示例,如下所示:

<order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MyProject.Models">
  <data>
    <shipments>
      <shipment>
        <giftnote />
        <products>
          <lineitem>
            <attributes>
              <attribute>
                <id>64</id>
              </attribute>
            </attributes>
            <description />
            <images>
              <orderDataShipmentsShipmentProductsLineitemImage>
                <no>64</no>
                <url>sample string 1</url>
              </orderDataShipmentsShipmentProductsLineitemImage>
              <orderDataShipmentsShipmentProductsLineitemImage>
                <no>64</no>
                <url>sample string 1</url>
              </orderDataShipmentsShipmentProductsLineitemImage>
              <orderDataShipmentsShipmentProductsLineitemImage>
                <no>64</no>
                <url>sample string 1</url>
              </orderDataShipmentsShipmentProductsLineitemImage>
            </images>
            <mc_order />
            <number>64</number>
            <quantity>64</quantity>
            <sku>sample string 2</sku>
          </lineitem>
        </products>
        <shipattributes />
        <shippinginfo>
          <address1>sample string 2</address1>
          <address2 />
          <city>sample string 4</city>
          <country>sample string 7</country>
          <emailAddress>sample string 9</emailAddress>
          <method>64</method>
          <name>sample string 1</name>
          <phone />
          <shipCharge>11</shipCharge>
          <state>sample string 5</state>
          <zip>6</zip>
        </shippinginfo>
      </shipment>
    </shipments>
  </data>
  <header>
    <OriginalNumber />
    <billinginfo>
      <address1>sample string 2</address1>
      <address2 />
      <cc>
        <amt>sample string 4</amt>
        <ccv>sample string 3</ccv>
        <exp>sample string 2</exp>
        <number>sample string 1</number>
      </cc>
      <city>sample string 4</city>
      <country>sample string 7</country>
      <emailAddress>sample string 9</emailAddress>
      <name>sample string 1</name>
      <phone>8</phone>
      <state>sample string 5</state>
      <zip>6</zip>
    </billinginfo>
    <customerClient>
      <id>sample string 1</id>
    </customerClient>
    <customerOrderNumber>sample string 2</customerOrderNumber>
    <date>sample string 1</date>
    <number>sample string 3</number>
    <organization>
      <id>64</id>
    </organization>
    <status>
      <id>64</id>
    </status>
  </header>
</order>

这是控制器代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using MyProject.Models;

namespace MyProject.Controllers
{
    public class LegacyOrdersController : ApiController
    {
        static readonly ILegacyOrderRepository repository = new LegacyOrderRepository();

        public HttpResponseMessage PostOrder([FromBody]order order) <--this is null
        {
            order = repository.Add(order);
            var response = Request.CreateResponse<order>(HttpStatusCode.Created, order);

            string uri = Url.Link("DefaultApi", new { id = order.header.customerOrderNumber });
            response.Headers.Location = new Uri(uri);
            return response;
        }
    }
}

【问题讨论】:

  • 我认为这里的问题在于 Xml 元素的顺序...请注意 &lt;header&gt; 标记放置在原始 xml 中的位置和帮助页面生成的 xml...帮助页面生成xml 使用 web api 的内置 Xml 格式化程序(默认情况下)使用DataContractSerializer(DCS)...具有 DCS 理解的DataContract 等属性,您可以以特定方式对元素进行排序...但是我不确定如果 DCS 将遵循 XmlElement 之类的属性来订购...或者您可以在 web api xml 格式化程序中使用 XmlSerializer ..
  • 我也看到了,但不知道为什么会这样。您能否进一步解释如何使用 XmlSerializer 来完成此操作?
  • 你可以通过config.Formatters.XmlFormatter.UseXmlSerializer = true;在webapi中启用xml序列化器
  • 粘贴为 XML 会生成一些丑陋的代码。您可以从小处着手,手动对模型进行编码以逐段匹配 xml,直到它起作用。这会很耗时,但你的模型会更干净。

标签: c# xml asp.net-mvc asp.net-web-api


【解决方案1】:

您使用错误的 XML 开始粘贴操作。获取从 Web API 帮助页面生成的 XML 并使用它。您会注意到生成的类的元素顺序与从原始 XML 生成的代码不同。

此外,为了简化传入的 XML,您可以配置为使用 XmlSerializer,如另一个 stackoverflow 帖子 (Serializer link) 所示

config.Formatters.XmlFormatter.UseXmlSerializer = true;

我还在所有生成的分类购买中添加了[Serializable],我不确定这是否真的需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    相关资源
    最近更新 更多