C # MVC Instant response to browser?

Again, asking MVC Noob questions. Forgive my lack of experience.

I have a situation where I use the MVC route to return a large XML file. Sometimes it can be very big. I am currently using StringBuilder to generate the XML output I want, and then return it as follows:

var sb = new StringBuilder(); XmlObject.WriteXml(sb); return Content(sb.ToString(), "text/xml", Encoding.UTF8); 

What I'm using is that (for various reasons) an XML blog can take quite some time.

Inside the XmlObject.WriteXml () method, there are tons of calls to other small methods that output XML bits and fragments as they are called, so I START building an XML line right away, it will take some time to finish. Each of these methods takes a StringBuilder as an argument, so it can create one and then pass it around the place using sb.Append () in each small method to build the final XML block.

OK, so I would like to start returning something to the client as soon as the line starts building. In Webforms, I would replace all StringBuilder parameters with HttpResponse parameters and use HttpResponse.Write () instead of StringBuilder.Append () like this:

 this.Response.BufferOutput = false; XmlObject.WriteXml(Response); 

Then, when each small piece of XML has been recorded in response, the text will be sent to the client.

The problem I am facing is that the ActionResult must have a return statement. I do not know how to treat in a similar fasion using the MVC route and ActionResult. Maybe I need to use something other than ActionResult?

Thanks everyone!

+4
source share
5 answers

If this does not have to be the result of an MVC action, and you do not want to break testability / encapsulation there, you can do it the way we always did it - using the custom IHttpHandler that directly flows into the response.

UPDATE

The sample may not make sense - you have a concept in your question. Only the twist was supposed to skip StringBuilder and use an XmlTextWriter for the stream in Response.OutputStream to skip the broker.

However, now that I am reading what you are doing, I personally accept "build autonomously and cache intelligently," rather than worry about streaming. Its probably easier to deal with canned food than to live.

+2
source

You can change the action method to return void , and then write directly to the response.
(Maybe I tried)

+4
source

Creating large volumes of XML with StringBuilder can put significant pressure on your memory. If you can write XML in depth order, use XmlTextWriter .

Here is sample code for writing a potentially large amount of XML to the output stream:

 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; } 

This specific example is an abridged version of some code that I use to write XML content in a sitemap.xml document. In my case, the document has about 30,000 URLs and has a size of about 2.5 MB.

+2
source
 public ActionResult Xml() { string xmlString = "xml goes here..."; return this.Content(xmlString, "text/xml", Encoding.UTF8); } 

ActionResult caching may be required if you do not want to regenerate it with every request. Look at the [OutputCache] attribute, you can cache it by parameter for a specified amount of time, etc.

I'm not sure what you are getting, it looks like you want to make some kind of asynchronous HTTP request. Generally speaking, this is not so. The client sends an HTTP request, the server generates and sends a response.

0
source

You can always load the page and display friendly content, and then use AJAX to invoke an action method that does the dirty work.

0
source

All Articles