如何将xml作为UTF-8而不是UTF-16返回

rwk*_*iii 12 c# xml utf-8 xml-serialization

我正在使用序列化的例程<T>.它可以工作,但当下载到浏览器时,我看到一个空白页面.我可以在文本编辑器中查看页面源或打开下载,我看到xml,但它是UTF-16,我认为这是为什么浏览器页面显示空白?

如何修改序列化程序例程以返回UTF-8而不是UTF-16?

XML源返回:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <string>January</string>
  <string>February</string>
  <string>March</string>
  <string>April</string>
  <string>May</string>
  <string>June</string>
  <string>July</string>
  <string>August</string>
  <string>September</string>
  <string>October</string>
  <string>November</string>
  <string>December</string>
  <string />
</ArrayOfString>
Run Code Online (Sandbox Code Playgroud)

调用序列化程序的示例:

DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo();
var months = dateTimeFormatInfo.MonthNames.ToList();

string SelectionId = "1234567890";

return new XmlResult<List<string>>(SelectionId)
{
    Data = months
};
Run Code Online (Sandbox Code Playgroud)

串行器:

public class XmlResult<T> : ActionResult
{
    private string filename = DateTime.Now.ToString("ddmmyyyyhhss");

    public T Data { private get; set; }

    public XmlResult(string selectionId = "")
    {
        if (selectionId != "")
        {
            filename = selectionId;
        }
    }

    public override void ExecuteResult(ControllerContext context)
    {
        HttpContextBase httpContextBase = context.HttpContext;
        httpContextBase.Response.Buffer = true;
        httpContextBase.Response.Clear();

        httpContextBase.Response.AddHeader("content-disposition", "attachment; filename=" + filename + ".xml");
        httpContextBase.Response.ContentType = "text/xml";

        using (StringWriter writer = new StringWriter())
        {
            XmlSerializer xml = new XmlSerializer(typeof(T));
            xml.Serialize(writer, Data);
            httpContextBase.Response.Write(writer);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Yis*_*zer 23

您可以使用强制UTF8的StringWriter.这是一种方法:

public class Utf8StringWriter : StringWriter
{
    // Use UTF8 encoding but write no BOM to the wire
    public override Encoding Encoding
    {
         get { return new UTF8Encoding(false); } // in real code I'll cache this encoding.
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在代码中使用Utf8StringWriter编写器.

using (StringWriter writer = new Utf8StringWriter())
{
    XmlSerializer xml = new XmlSerializer(typeof(T));
    xml.Serialize(writer, Data);
    httpContextBase.Response.Write(writer);
}
Run Code Online (Sandbox Code Playgroud)

答案的灵感来自将对象序列化为.NET中的UTF-8 XML


Nob*_*are 8

响应的编码

我对框架的这一部分不是很熟悉.但根据MSDN,您可以设置HttpResponse内容编码,如下所示:

httpContextBase.Response.ContentEncoding = Encoding.UTF8;
Run Code Online (Sandbox Code Playgroud)

XmlSerializer看到的编码

在再次阅读你的问题后,我发现这是一个艰难的部分.问题在于使用StringWriter.因为.NET字符串总是存储为UTF-16(引用需要^^),所以StringWriter将其作为编码返回.因此,XmlSerializer将XML声明写为

<?xml version="1.0" encoding="utf-16"?>
Run Code Online (Sandbox Code Playgroud)

要解决这个问题,您可以像这样写入MemoryStream:

using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
    XmlSerializer xml = new XmlSerializer(typeof(T));
    xml.Serialize(writer, Data);

    // I am not 100% sure if this can be optimized
    httpContextBase.Response.BinaryWrite(stream.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

其他方法

另一个编辑:我刚刚注意到这个由jtm001链接的SO答案.简化了解决方案,提供了XmlSerializer一个XmlWriter配置为使用UTF8作为编码的自定义.

Athari 建议派生出来StringWriter并将编码宣传为UTF8.

据我所知,两种解决方案都应该有效.我认为这里的外卖是你需要一种样板代码或其他代码......