C#MVC对浏览器的即时响应?

时间:2010-11-05 20:51:53

标签: asp.net-mvc asp.net-mvc-routing httpresponse actionresult

再次,询问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以外的东西?

谢谢大家!

5 个答案:

答案 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调用执行脏工作的操作方法。