再次,询问MVC noob问题。原谅我缺乏经验。
我有一种情况,我使用MVC路由返回一个大型XML文件。有时它可能非常大。目前,我正在使用StringBuilder来构建我想要的XML输出,然后像这样返回它:
var sb = new StringBuilder();
XmlObject.WriteXml(sb);
return Content(sb.ToString(), "text/xml", Encoding.UTF8);
我遇到的是(由于各种原因)XML博客可能需要很长时间才能生成。
在XmlObject.WriteXml()方法中调用了许多其他小方法,这些方法在调用时输出XML的一些部分,因此我立即开始构建XML字符串,只需要一段时间即可完成。这些方法中的每一个都接受一个StringBuilder作为参数,因此可以创建一个然后将它传递到整个地方,在每个小方法中使用sb.Append()来构建最终的XML blob。
好的,所以我想做的就是在字符串开始构建时立即向客户端返回一些东西。在Webforms中,我会用HttpResponse替换所有StringBuilder参数,并使用HttpResponse.Write()而不是StringBuilder.Append(),方式类似于:
this.Response.BufferOutput = false;
XmlObject.WriteXml(Response);
然后,当每一小段XML写入Reponse时,文本将被发送给客户端。
我遇到的问题是ActionResult必须有一个return语句。我不知道如何使用MVC路线和ActionResult在类似的时尚中对待。也许我需要使用ActionResult以外的东西?
谢谢大家!
答案 0 :(得分:4)
您可以将操作方法更改为返回void
,然后直接写入回复
(这是可能的;我已经尝试过了)
答案 1 :(得分:2)
如果它不需要是MVC操作的结果,并且您不想破坏可测试性/封装,那么您可以按照我们总是这样做的方式 - 使用直接流入的自定义IHttpHandler回应。
的更新强> 的
样本可能没有意义 - 你的问题中有这个概念。只有扭曲才能跳过StringBuilder并使用XmlTextWriter集流式传输到Response.OutputStream以跳过中间人。
那就是说,现在我正在阅读你正在做的事情,我个人会采取“构建离线和合理缓存”的角度,而不是担心流式传输。它可能更容易处理罐头而不是生活。
答案 2 :(得分:2)
使用StringBuilder
构建大量XML会给您的内存带来很大压力。如果您可以按深度优先顺序编写XML,请使用XmlTextWriter
。
以下是将大量XML写入输出流的示例代码:
public ActionResult SiteMap()
{
Response.ClearContent();
Response.ContentType = "application/xml";
Response.ContentEncoding = Encoding.UTF8;
using (var context = new MyDataContext())
{
using (var xml = new XmlTextWriter(Response.Output))
{
xml.WriteStartElement("urlset",
"http://www.sitemaps.org/schemas/sitemap/0.9");
var url = new UrlHelper(Request.RequestContext);
xml.WriteStartElement("url");
xml.WriteElementString("loc", /* some URL */);
xml.WriteEndElement();
foreach (var blogPost in context.BlogPosts)
{
xml.WriteStartElement("url");
xml.WriteElementString("loc", /* blog post URL */);
xml.WriteEndElement();
}
xml.WriteEndElement();
xml.Flush();
}
}
return null;
}
这个特殊的例子是我用来写出sitemap.xml
文档的XML内容的一些代码的缩写版本。在我的情况下,该文档有大约30,000个URL,大小约为2.5MB。
答案 3 :(得分:0)
public ActionResult Xml()
{
string xmlString = "xml goes here...";
return this.Content(xmlString, "text/xml", Encoding.UTF8);
}
如果您不想在每个请求上重新生成ActionResult,可能会考虑缓存它。查看[OutputCache]属性,您可以按参数,指定的时间等缓存它。
我不确定你得到了什么,听起来你想做某种异步的http请求。一般来说,他们不是。客户端发送http请求,服务器生成并发回响应。
答案 4 :(得分:0)
您可以随时首先加载页面并显示友好内容,然后使用AJAX调用执行脏工作的操作方法。