对于在 ASP.NET 中返回 XML 的任务,我遇到过许多半解决方案。不过,我不想盲目地复制和粘贴一些大多数时候都能正常工作的代码;我想要正确的代码,并且我想知道为什么它是正确的。我要批评;我想要信息;我要知识;我想要理解。
下面是代码片段,按照复杂性递增的顺序,代表我见过的一些部分解决方案,包括每个问题引起的一些进一步问题,我想在这里回答这些问题。
一个完整的答案必须说明为什么我们必须有或不能有以下任何东西,或者解释为什么它不相关。
最后,假设您需要像这样编写辅助函数的内容:
///<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 更改为 "text/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 之后还可能发生什么这需要我们立即结束响应吗?
是 text/xml 的内容类型足够了,还是应该改为 text/xml; charset=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 .这个好吗?坏的?更好的?更差?快点?慢点?内存更密集?更少的内存占用?
我read你应该渲染
the XML in the page’s Render() method to avoid problems with chunking encountered when using Page_Load().
什么是分块?
分块有什么问题,如何使用 Page_Render消灭他们?
我不想写我的 XmlDocument 的内容object 到一个字符串中,然后写入它,因为这会浪费内存。也就是说,任何这些都是不好的:
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
最佳答案
我找到了在 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)
不要使用Response.OutputStream
做使用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 声明或网络服务器响应的内容编码不匹配。
不正确:
Response.Write(doc.ToString());
Response.Write(doc.InnerXml);
此处 XML 被错误地转换为没有编码的字符串。 XML 声明节点未更新以反射(reflect)响应的编码,并且响应未正确编码以匹配响应的编码。此外,将 XML 存储在中间字符串中会浪费内存。
您不想将 XML 保存为字符串,或将 XML 塞入字符串并response.Write 一个字符串,因为:
- doesn't follow the encoding specified
- doesn't set the XML declaration node to match
- wastes memory
做使用doc.Save(Response.Output);
不要使用doc.Save(Response.OutputStream);
不要使用Response.Write(doc.ToString());
不要使用'Response.Write(doc.InnerXml);`
Response 的 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
Rob Kennedy 的观点很好,我没有包括从开始到结束的示例。
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; } }
}
关于c# - 如何在 ASP.NET 中返回 XML?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/543319/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"