1

几个小时以来,我一直在努力从 ASP.NET Web Api 中序列化我的独立对象(不是 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);
    }
}

问题是,当我使用有效的字符串参数调用 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:xsixmlns:xsd. 事实上,当它看到命名空间时,它会返回一个异常。

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

我看到了这个帖子这个。虽然前者非常详细,但它并没有解决我的问题。它只是xmlns为生成的 XML 引入了一个额外的内容。我认为这是因为我没有.Serialize()XmlSerializer.

我想出了一个解决方案,我想我应该分享一下。所以我会在答案中说明它。

4

1 回答 1

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>

我希望这可以帮助别人。

于 2013-04-08T13:31:18.653 回答