对于在ASP.NET中返回XML的任务,我遇到了许多半途而废的解决方案,但我不想盲目地复制和粘贴一些在大多数情况下都可以工作的代码;我想要正确的代码,我想知道为什么它是正确的。我需要批评;我需要信息;我需要知识;我需要理解。
下面是代码片段,按复杂性递增的顺序,代表了我所见过的一些部分解决方案,包括每个解决方案引起的一些进一步的问题,我希望在这里得到答案。
一个完整的答案必须解决为什么我们必须有或不能有以下任何东西,或者解释为什么它是不相关的。
最后,假设您需要像这样编写一个helper函数的内容:
///<summary>Use this call inside your (Page_Xxx) method to write the
///xml to the web client. </summary>
///<remarks>See for https://stackoverflow.com/questions/543319/how-to-return-xml-in-asp-net
///for proper usage.</remarks>
public static void ReturnXmlDocumentToWebClient(
XmlDocument document,
Page page)
{
...
}
我看到的每个解决方案都是从获取一个空的aspx页面开始,并修剪掉前面文件中的所有HTML (这会在Visual Studio中引起警告):
<%@ Page Language="C#"
AutoEventWireup="true"
CodeFile="GetTheXml.aspx.cs"
Inherits="GetTheXml" %>
接下来,我们使用Page_Load
事件来写入输出:
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.Write(xml);
}
我们是否需要将文本ContentType更改为“/xml”?即:
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.ContentType = "text/xml";
Response.Write(xml);
}
我们需要先调用Response.Clear
吗?
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.Clear();
Response.ContentType = "text/xml";
Response.Write(xml);
}
我们真的需要这样做吗?难道Response.Clear
不需要在<% ... %>
之外确保前面文件中的代码为空(甚至没有空格或回车符)吗?
如果有人在代码前端文件中留下了空行或空格,Response.Clear
是否会使其更加健壮?
使用ashx是否与空白aspx主文件相同,因为可以理解它不会输出HTML?
我们需要给Response.End
打电话吗?即:
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.Clear();
Response.ContentType = "text/xml";
Response.Write(xml);
Response.End();
}
在Response.Write
之后还会发生什么,需要我们立即结束响应
字符集的内容类型是否足够,或者应该改为文本/xml;text/xml
=utf-8
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.Clear();
Response.ContentType = "text/xml; charset=utf-8";
Response.Write(xml);
Response.End();
}
或者应该明确地说是而不是?在内容类型中有一个字符集,但没有设置属性,会不会搞砸服务器?
为什么不是一些其他的内容类型,例如:
是否应在Response.ContentEncoding
中指定字符集
protected void Page_Load(object sender, EventArgs e)
{
String xml = "<foo>Hello, world!</foo>";
Response.Clear();
Response.ContentType = "text/xml";
Response.ContentEncoding = Encoding.UTF8;
Response.Write(xml);
Response.End();
}
使用Response.ContentEncoding
比把它塞进Response.ContentType
更好吗?是不是更糟?支持前者吗?是后者吗?
我实际上并不想写出一个字符串;我想写出一个XmlDocument
。Someone suggests I can use the XmlWriter
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument xml = GetXmlDocumentToShowTheUser();
Response.Clear();
Response.ContentType = "text/xml";
Response.ContentEncoding = Encoding.UTF8;
using (TextWriter textWriter = new StreamWriter(
Response.OutputStream,
Encoding.UTF8))
{
XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
// Write XML using xmlWriter
//TODO: How to do this?
}
}
注意Response.OutputStream
的用法,而不是Response.Write
。这样好吗?坏的?好些了吗?更糟?更快?慢点?更多内存密集型?内存密集度更低?
I read,你应该渲染
在页面的
()方法中呈现XML,以避免在使用Page_Load()时遇到的分块问题。
什么是分块?分块有什么问题,使用Page_Render
如何消除这些问题?
我不希望将XmlDocument
对象的内容写入字符串,然后再将其写入,因为这会浪费内存。也就是说,任何这些都是不好的:
Response.Write(doc.ToString());
Response.Write(doc.InnerXml);
xmlWrite.WriteString(doc.ToString());
xmlWrite.WriteString(doc.InnerXml);
相似问题
参考
How Return XML From ASPX in ASP.NET 1.1
Writing XML output to an ASP.NET webpage
发布于 2010-01-30 00:37:30
我已经找到了在ASP.NET中将XML返回给客户机的正确方法,我想如果我指出了错误的方法,那么正确的方法会更容易理解。
不正确:
Response.Write(doc.ToString());
不正确:
Response.Write(doc.InnerXml);
不正确:
Response.ContentType = "text/xml";
Response.ContentEncoding = System.Text.Encoding.UTF8;
doc.Save(Response.OutputStream);
正确:
Response.ContentType = "text/xml"; //Must be 'text/xml'
Response.ContentEncoding = System.Text.Encoding.UTF8; //We'd like UTF-8
doc.Save(Response.Output); //Save to the text-writer
//using the encoding of the text-writer
//(which comes from response.contentEncoding)
使用TextWriter
Do not use Response.OutputStream
吗?
Do use Response.Output
两者都是流,但Output
是一个TextWriter。当XmlDocument
将自身保存到 TextWriter 时,它将使用该TextWriter指定的编码。XmlDocument将自动更改xml声明节点以匹配TextWriter使用的编码。例如,在本例中,XML声明节点:
<?xml version="1.0" encoding="ISO-8859-1"?>
会变成
<?xml version="1.0" encoding="UTF-8"?>
这是因为TextWriter已设置为UTF-8。(稍后将对此进行详细介绍)。当TextWriter获得字符数据时,它将使用适合其集合编码的字节序列对其进行编码。
不正确的
doc.Save(Response.OutputStream);
在本例中,文档被错误地保存到OutputStream,它不执行任何编码更改,并且可能与响应的内容编码或XML声明节点指定的编码不匹配。
正确的
doc.Save(Response.Output);
XML文档被正确地保存到TextWriter对象中,从而确保正确地处理编码。
设置编码
header中提供给客户端的编码:
Response.ContentEncoding = ...
必须与XML文档的编码匹配:
<?xml version="1.0" encoding="..."?>
必须与发送到客户端的字节序列中的实际编码相匹配。要使这三件事都一致,只需设置一行:
Response.ContentEncoding = System.Text.Encoding.UTF8;
在Response对象上设置编码时,它会在TextWriter上设置相同的编码。TextWriter的编码集导致XmlDocument更改xml声明
<?xml version="1.0" encoding="UTF-8"?>
保存文档时:
doc.Save(someTextWriter);
保存到响应输出
您不希望将文档保存为二进制流,或写入字符串:
不正确:
doc.Save(Response.OutputStream);
在这里,XML被错误地保存为二进制流。最终的字节编码序列将与XML声明或web服务器响应的内容编码不匹配。
不正确:
Response.Write(doc.ToString());
Response.Write(doc.InnerXml);
在这里,XML被错误地转换为没有编码的字符串。XML声明节点没有更新以反映响应的编码,并且响应没有正确编码以匹配响应的编码。此外,将XML存储在中间字符串中也会浪费内存。
您不希望将XML保存为字符串,或者将XML填充到一个字符串中然后对一个字符串执行response.Write
操作,因为:
- doesn't follow the encoding specified
- doesn't set the XML declaration node to match
- wastes memory
Do use doc.Save(Response.Output);
Do not use doc.Save(Response.OutputStream);
吗?
Do not use Response.Write(doc.ToString());
吗?
Do not use 'Response.Write(doc.InnerXml);`
设置content-type
响应的ContentType必须设置为"text/xml"
。如果不是,客户端将不知道您正在向它发送XML。
最终答案
Response.Clear(); //Optional: if we've sent anything before
Response.ContentType = "text/xml"; //Must be 'text/xml'
Response.ContentEncoding = System.Text.Encoding.UTF8; //We'd like UTF-8
doc.Save(Response.Output); //Save to the text-writer
//using the encoding of the text-writer
//(which comes from response.contentEncoding)
Response.End(); //Optional: will end processing
完整示例
罗布·肯尼迪有一个很好的观点,那就是我没有包括从头到尾的例子。
GetPatronInformation.ashx
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
using System.Xml;
using System.IO;
using System.Data.Common;
//Why a "Handler" and not a full ASP.NET form?
//Because many people online critisized my original solution
//that involved the aspx (and cutting out all the HTML in the front file),
//noting the overhead of a full viewstate build-up/tear-down and processing,
//when it's not a web-form at all. (It's a pure processing.)
public class Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//GetXmlToShow will look for parameters from the context
XmlDocument doc = GetXmlToShow(context);
//Don't forget to set a valid xml type.
//If you leave the default "text/html", the browser will refuse to display it correctly
context.Response.ContentType = "text/xml";
//We'd like UTF-8.
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
//context.Response.ContentEncoding = System.Text.Encoding.UnicodeEncoding; //But no reason you couldn't use UTF-16:
//context.Response.ContentEncoding = System.Text.Encoding.UTF32; //Or UTF-32
//context.Response.ContentEncoding = new System.Text.Encoding(500); //Or EBCDIC (500 is the code page for IBM EBCDIC International)
//context.Response.ContentEncoding = System.Text.Encoding.ASCII; //Or ASCII
//context.Response.ContentEncoding = new System.Text.Encoding(28591); //Or ISO8859-1
//context.Response.ContentEncoding = new System.Text.Encoding(1252); //Or Windows-1252 (a version of ISO8859-1, but with 18 useful characters where they were empty spaces)
//Tell the client don't cache it (it's too volatile)
//Commenting out NoCache allows the browser to cache the results (so they can view the XML source)
//But leaves the possiblity that the browser might not request a fresh copy
//context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
//And now we tell the browser that it expires immediately, and the cached copy you have should be refreshed
context.Response.Expires = -1;
context.Response.Cache.SetAllowResponseInBrowserHistory(true); //"works around an Internet Explorer bug"
doc.Save(context.Response.Output); //doc saves itself to the textwriter, using the encoding of the text-writer (which comes from response.contentEncoding)
#region Notes
/*
* 1. Use Response.Output, and NOT Response.OutputStream.
* Both are streams, but Output is a TextWriter.
* When an XmlDocument saves itself to a TextWriter, it will use the encoding
* specified by the TextWriter. The XmlDocument will automatically change any
* XML declaration node, i.e.:
* <?xml version="1.0" encoding="ISO-8859-1"?>
* to match the encoding used by the Response.Output's encoding setting
* 2. The Response.Output TextWriter's encoding settings comes from the
* Response.ContentEncoding value.
* 3. Use doc.Save, not Response.Write(doc.ToString()) or Response.Write(doc.InnerXml)
* 3. You DON'T want to save the XML to a string, or stuff the XML into a string
* and response.Write that, because that
* - doesn't follow the encoding specified
* - wastes memory
*
* To sum up: by Saving to a TextWriter: the XML Declaration node, the XML contents,
* and the HTML Response content-encoding will all match.
*/
#endregion Notes
}
private XmlDocument GetXmlToShow(HttpContext context)
{
//Use context.Request to get the account number they want to return
//GET /GetPatronInformation.ashx?accountNumber=619
//Or since this is sample code, pull XML out of your rear:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Patron><Name>Rob Kennedy</Name></Patron>");
return doc;
}
public bool IsReusable { get { return false; } }
}
发布于 2009-02-12 21:44:48
下面是我认为正确方法的一个例子。至少我是这么用的。您需要执行Response.Clear来清除任何已填充的标头。您需要传递文本/xml的正确ContentType。这就是为xml提供服务的方式。通常,您希望将其作为字符集UTF-8,因为这是大多数解析器所期望的。但我不认为这是必须的。但是,如果更改了它,请确保更改xml文档声明并在其中指明字符集。您需要使用XmlWriter,这样您才能实际使用UTF-8编写代码,而不是使用任何默认字符集。并让它以UTF-8格式对xml数据进行正确编码。
' -----------------------------------------------------------------------------
' OutputDataSetAsXML
'
' Description: outputs the given dataset as xml to the response object
'
' Arguments:
' dsSource - source data set
'
' Dependencies:
'
' History
' 2006-05-02 - WSR : created
'
Private Sub OutputDataSetAsXML(ByRef dsSource As System.Data.DataSet)
Dim xmlDoc As System.Xml.XmlDataDocument
Dim xmlDec As System.Xml.XmlDeclaration
Dim xmlWriter As System.Xml.XmlWriter
' setup response
Me.Response.Clear()
Me.Response.ContentType = "text/xml"
Me.Response.Charset = "utf-8"
xmlWriter = New System.Xml.XmlTextWriter(Me.Response.OutputStream, System.Text.Encoding.UTF8)
' create xml data document with xml declaration
xmlDoc = New System.Xml.XmlDataDocument(dsSource)
xmlDoc.DataSet.EnforceConstraints = False
xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)
xmlDoc.PrependChild(xmlDec)
' write xml document to response
xmlDoc.WriteTo(xmlWriter)
xmlWriter.Flush()
xmlWriter.Close()
Response.End()
End Sub
' -----------------------------------------------------------------------------
发布于 2009-02-12 22:18:33
这里似乎至少有10个问题集中在一个问题上,有几个要点。
Response.Clear -这真的取决于应用程序中还发生了什么-如果你在管道的早期有可能正在编写你不想要的东西的httpmodules然后清除它。测试它并找出答案。Fiddler或Wireshark对此很有用。
Content Type to text/xml - yup -好主意-阅读HTTP规范,了解为什么这很重要。我想任何从事网络工作的人都应该至少阅读过1.0和1.1规范一次。
编码-您的xml是如何编码的-如果它是utf-8,那么就说出来,如果不是,就说一些其他合适的东西,只要确保它们都匹配即可。
页面-就我个人而言,如果你正在使用页面,并且想要更快一点,我会使用ashx或httpmodule,去掉autoeventwireup并手动绑定事件处理程序。
首先将xml转储到字符串中可能有点浪费内存,但这在很大程度上取决于xml的大小,您是否会注意到这一点。
正如其他人所建议的,将xml保存到输出流可能是最快的,我通常会这样做,但如果您不确定,请测试它,不要依赖于您在互联网上读到的内容。不要只相信我说的任何话。
对于另一种方法,如果xml没有太多变化,您可以直接将其写入磁盘并直接提供文件,这可能会有很高的性能,但就像编程中的所有事情一样,这取决于...
https://stackoverflow.com/questions/543319
复制相似问题