首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在ASP.NET中返回XML?

如何在ASP.NET中返回XML?
EN

Stack Overflow用户
提问于 2009-02-12 21:19:21
回答 8查看 113.7K关注 0票数 64

对于在ASP.NET中返回XML的任务,我遇到了许多半途而废的解决方案,但我不想盲目地复制和粘贴一些在大多数情况下都可以工作的代码;我想要正确的代码,我想知道为什么它是正确的。我需要批评;我需要信息;我需要知识;我需要理解。

下面是代码片段,按复杂性递增的顺序,代表了我所见过的一些部分解决方案,包括每个解决方案引起的一些进一步的问题,我希望在这里得到答案。

一个完整的答案必须解决为什么我们必须有或不能有以下任何东西,或者解释为什么它是不相关的。

  • Response.Clear();
  • Response.ContentType = "text/xml";
  • Response.ContentEncoding = Encoding.UTF8;
  • Response.ContentEncoding = Encoding.UTF16;
  • Response.ContentType = "text/xml;charset=utf-8";
  • Response.ContentType = "text/xml;charset=utf-16";
  • Response.End()
  • Using带有正面文件内脏的aspx使用

最后,假设您需要像这样编写一个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();
}

或者应该明确地说是而不是?在内容类型中有一个字符集,但没有设置属性,会不会搞砸服务器?

为什么不是一些其他的内容类型,例如:

  • UTF-8
  • utf-16
  • UTF-16

是否应在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更好吗?是不是更糟?支持前者吗?是后者吗?

我实际上并不想写出一个字符串;我想写出一个XmlDocumentSomeone 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 to return XML in ASP.NET

参考

How Return XML From ASPX in ASP.NET 1.1

Writing XML output to an ASP.NET webpage

How do you output XML from ASP.NET?

Creating an ASHX handler in ASP.NET

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 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&nbsp;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; } }
}
票数 73
EN

Stack Overflow用户

发布于 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
   ' -----------------------------------------------------------------------------
票数 0
EN

Stack Overflow用户

发布于 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没有太多变化,您可以直接将其写入磁盘并直接提供文件,这可能会有很高的性能,但就像编程中的所有事情一样,这取决于...

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/543319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档