问题描述
我正在使用序列化<T>
的例程.它可以工作,但是当下载到浏览器时,我看到一个空白页.我可以查看页面源代码,也可以在文本编辑器中打开下载文件,然后看到xml,但是它是UTF-16,我认为这就是为什么浏览器页面显示空白?
I am using a routine that serializes <T>
. It works, but when downloaded to the browser I see a blank page. I can view the page source or open the download in a text editor and I see the xml, but it is in UTF-16 which I think is why browser pages show blank?
如何修改序列化程序例程以返回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>
对序列化程序的调用示例:
An example call to the serializer:
DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo();
var months = dateTimeFormatInfo.MonthNames.ToList();
string SelectionId = "1234567890";
return new XmlResult<List<string>>(SelectionId)
{
Data = months
};
序列化器:
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);
}
}
}
推荐答案
响应的编码
我对框架的这一部分不太熟悉.但是根据MSDN,您可以设置:
httpContextBase.Response.ContentEncoding = Encoding.UTF8;
XmlSerializer看到的
编码
再次阅读您的问题后,我发现这是困难的部分.问题在于使用StringWriter
.因为.NET字符串始终存储为UTF-16(需要引用,请^^),因此StringWriter
将此作为其编码返回.因此,XmlSerializer
将XML声明写为
Encoding as seen by the XmlSerializer
After reading your question again I see that this is the tough part. The problem lies within the use of the StringWriter
. Because .NET Strings are always stored as UTF-16 (citation needed ^^) the StringWriter
returns this as its encoding. Thus the XmlSerializer
writes the XML-Declaration as
<?xml version="1.0" encoding="utf-16"?>
要解决此问题,您可以像这样写入MemoryStream:
To work around that you can write into an MemoryStream like this:
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());
}
其他方法
另一种我刚刚注意到由jtm001链接的这样的答案.浓缩的解决方案是为XmlSerializer
提供一个自定义的XmlWriter
,该XmlWriter
被配置为使用UTF8作为编码.
Another edit: I just noticed this SO answer linked by jtm001. Condensed the solution there is to provide the XmlSerializer
with a custom XmlWriter
that is configured to use UTF8 as encoding.
Athari 建议从StringWriter
派生,并将其广告编码为UTF8.
Athari proposes to derive from the StringWriter
and advertise the encoding as UTF8.
据我了解,这两种解决方案也都应该起作用.我认为这里的要点是您将需要一种样板代码或另一种样板代码.
To my understanding both solutions should work as well. I think the take-away here is that you will need one kind of boilerplate code or another...
这篇关于如何以utf-8而不是utf-16返回xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!