【发布时间】: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 元素的顺序...请注意
<header>标记放置在原始 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