C# 如何从Web API XML序列化程序中删除xmlns:xsi和xmlns:xsd

C# 如何从Web API XML序列化程序中删除xmlns:xsi和xmlns:xsd,c#,asp.net-web-api,xmlserializer,C#,Asp.net Web Api,Xmlserializer,几个小时以来,我一直在努力从ASP.NETWebAPI中序列化独立对象(不是MVC模型)返回的XML中删除默认名称空间。应用程序的示例代码为: 类别定义: public class PaymentNotificationResponse { [XmlArray("Payments")] [XmlArrayItem("Payment", typeof(PaymentResponse))] public PaymentResponse[] Payments { get; s

几个小时以来,我一直在努力从ASP.NETWebAPI中序列化独立对象(不是MVC模型)返回的XML中删除默认名称空间。应用程序的示例代码为:

类别定义:

public class PaymentNotificationResponse
{

    [XmlArray("Payments")]
    [XmlArrayItem("Payment", typeof(PaymentResponse))]
    public PaymentResponse[] Payments { get; set; }
}
然后,我创建了一个Web Api控件,它根据一些输入创建
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);
    }
}
公共类付费控制器:ApiController
{
公共付款通知回复帖子()
{
//读取请求内容(仅异步可用),运行任务以完成并拾取流。
var strmTask=Request.Content.ReadAsStreamAsync();
while(strmTask.Status!=TaskStatus.RanToCompletion){}
Stream strm=strmTask.Result;
//返回到流的开头,以便可以检索数据。WebAPI将数据读取到结尾。
if(strm.CanSeek)
strm.Seek(0,SeekOrigin.Begin);
//读取流内容并转换为字符串。
字节[]arr=新字节[strm.Length];
标准读取(arr,0,arr.Length);
String str=Encoding.UTF8.GetString(arr);
//将默认序列化程序从DataContractSerializer更改为XmlSerializer,这样我就不会在属性中获得有趣的名称空间。
//然后为对象设置一个新的XmlSerializer
Configuration.Formatters.XmlFormatter.UseXmlSerializer=true;
Configuration.Formatters.XmlFormatter.SetSerializer(新的XmlSerializer(typeof(PaymentNotificationResponse));
//现在调用一个函数,将字符串转换为所需的对象,然后在调用Web Api时序列化该对象。
返回CreatePaymentNotificationFromString(str);
}
}
问题是,当我使用有效的字符串参数调用Api时,它返回这种格式的XML(有效的XML,但不需要xmlns):


8325
0
我将此信息发送到的系统不需要
xmlns:xsi
xmlns:xsd
。事实上,当它看到名称空间时,它会返回一个异常

我尝试返回一个带有XML标记的字符串,它只是将响应包装在一个
中,并对所有进行编码。所以这不是一个选择

我看了又看。虽然前者非常详细,但它并没有解决我的问题。它只为生成的XML引入了一个额外的
xmlns
。我想这是因为我没有在
XmlSerializer
中显式调用
.Serialize()
函数


我想出了一个解决办法,我想我应该和大家分享。因此,我会在回答中说明这一点。

为了解决这个问题,我添加了一个方法来序列化
PaymentNotificationResponse
并返回一个XML字符串,因此(我在
PaymentNotificationResponse
的定义中包含了这一点):

我解析了字符串以创建一个
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;
    }
这将使我的回答如下:

<PaymentNotificationResponse>
    <Payments>
        <Payment>
            <PaymentLogId>8325</PaymentLogId>
            <Status>0</Status>
        </Payment>
    </Payments>
</PaymentNotificationResponse>

8325
0
我希望这对某些人有所帮助。

很好的解决方案,“return XDocument.Parse(pnr.SerializeToXml()).Root;”是关键。
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;
    }
<PaymentNotificationResponse>
    <Payments>
        <Payment>
            <PaymentLogId>8325</PaymentLogId>
            <Status>0</Status>
        </Payment>
    </Payments>
</PaymentNotificationResponse>