几个小时以来,我一直在努力从ASP.NET Web Api中序列化我的独立对象(不是MVC模型)返回的XML中删除默认命名空间。该应用程序的示例代码为:
班级定义:
public class PaymentNotificationResponse
{
[XmlArray("Payments")]
[XmlArrayItem("Payment", typeof(PaymentResponse))]
public PaymentResponse[] Payments { get; set; }
}
然后我创建了一个Web Api Controler,它根据某些输入创建PaymentNotificationResponse
的对象,然后将对象序列化到请求方。控制器如下:
public class PaymentController : ApiController
{
public PaymentNotificationResponse Post()
{
//Read request content (only available async), run the task to completion and pick the stream.
var strmTask = Request.Content.ReadAsStreamAsync();
while (strmTask.Status != TaskStatus.RanToCompletion) { }
Stream strm = strmTask.Result;
//Go back to the beginning of the stream, so that the data can be retrieved. Web Api reads it to the end.
if (strm.CanSeek)
strm.Seek(0, SeekOrigin.Begin);
//Read stream content and convert to string.
byte[] arr = new byte[strm.Length];
strm.Read(arr, 0, arr.Length);
String str = Encoding.UTF8.GetString(arr);
//Change the default serializer to XmlSerializer from DataContractSerializer, so that I don't get funny namespaces in properties.
//Then set a new XmlSerializer for the object
Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Configuration.Formatters.XmlFormatter.SetSerializer<PaymentNotificationResponse>(new XmlSerializer(typeof(PaymentNotificationResponse)));
//Now call a function that would convert the string to the required object, which would then be serialized when the Web Api is invoked.
return CreatePaymentNotificationFromString(str);
}
}
问题是,当我用有效的字符串参数调用Api时,它返回这种格式的XML(有效的XML,但不需要xmlns):
<PaymentNotificationResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Payments>
<Payment>
<PaymentLogId>8325</PaymentLogId>
<Status>0</Status>
</Payment>
</Payments>
</PaymentNotificationResponse>
我发送给它的系统不需要xmlns:xsi
和xmlns:xsd
。实际上,它在看到命名空间时会返回异常。
我尝试使用XML标记返回一个字符串,它只是将响应包装在<string></string>
中并编码所有&lt;和&gt;。所以这不是一个选择。
我看到了this post和this one。虽然前者非常详细,但它并没有解决我的问题。它只是为生成的XML引入了一个额外的xmlns
。我认为这是因为我没有在.Serialize()
中明确调用XmlSerializer
函数。
我想出了一个解决方案,我想我应该分享一下。所以我会在答案中说明。
答案 0 :(得分:3)
为了解决这个问题,我添加了一个方法来序列化PaymentNotificationResponse
并返回一个XML字符串,因此(我将其包括在PaymentNotificationResponse
的定义中):
//I added this method after I tried serialize directly to no avail
public String SerializeToXml()
{
MemoryStream ms = new MemoryStream();
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
new XmlSerializer(typeof(PaymentNotificationResponse)).Serialize(ms, this, ns);
XmlTextWriter textWriter = new XmlTextWriter(ms, Encoding.UTF8);
ms = (System.IO.MemoryStream)textWriter.BaseStream;
return new UTF8Encoding().GetString(ms.ToArray());
}
我解析了字符串以创建XDocument
,然后返回根元素。这使我将Post()
方法的返回类型更改为XElement
。 Post()
列表将是:
public XElement Post()
{
//...Same as it was in the question, just the last line that changed.
var pnr = CreatePaymentNotificationFromString(str);
return XDocument.Parse(pnr.SerializeToXml()).Root;
}
这会使我的回复XML:
<PaymentNotificationResponse>
<Payments>
<Payment>
<PaymentLogId>8325</PaymentLogId>
<Status>0</Status>
</Payment>
</Payments>
</PaymentNotificationResponse>
我希望这有助于某人。