Writing to Output Stream from Action

前端 未结 5 702
悲&欢浪女
悲&欢浪女 2020-11-29 04:13

For some strange reasons, I want to write HTML directly to the Response stream from a controller action. (I understand MVC separation, but this is a special case.)

C

相关标签:
5条回答
  • 2020-11-29 04:27

    If you don't want to derive your own result type, you can simply write to Response.OutputStream and return new EmptyResult().

    0 讨论(0)
  • 2020-11-29 04:36

    You can do return Content(...); where, if I remember correctly, ... would be what you want to write directly to the output stream, or nothing at all.

    Take a look at the Content methods on the Controller: http://aspnet.codeplex.com/SourceControl/changeset/view/22907#266451

    And the ContentResult: http://aspnet.codeplex.com/SourceControl/changeset/view/22907#266450

    0 讨论(0)
  • 2020-11-29 04:41

    Write your own Action Result. Here's an example of one of mine:

    public class RssResult : ActionResult
    {
        public RssFeed RssFeed { get; set; }
    
        public RssResult(RssFeed feed) {
            RssFeed = feed;
        }
    
        public override void ExecuteResult(ControllerContext context) {
            context.HttpContext.Response.ContentType = "application/rss+xml";
            SyndicationResourceSaveSettings settings = new SyndicationResourceSaveSettings();
            settings.CharacterEncoding = new UTF8Encoding(false);
            RssFeed.Save(context.HttpContext.Response.OutputStream, settings);
        }
    }
    
    0 讨论(0)
  • 2020-11-29 04:43

    I used a class derived from FileResult to achieve this using normal MVC pattern:

    /// <summary>
    /// MVC action result that generates the file content using a delegate that writes the content directly to the output stream.
    /// </summary>
    public class FileGeneratingResult : FileResult
    {
        /// <summary>
        /// The delegate that will generate the file content.
        /// </summary>
        private readonly Action<System.IO.Stream> content;
    
        private readonly bool bufferOutput;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="FileGeneratingResult" /> class.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="contentType">Type of the content.</param>
        /// <param name="content">Delegate with Stream parameter. This is the stream to which content should be written.</param>
        /// <param name="bufferOutput">use output buffering. Set to false for large files to prevent OutOfMemoryException.</param>
        public FileGeneratingResult(string fileName, string contentType, Action<System.IO.Stream> content,bool bufferOutput=true)
            : base(contentType)
        {
            if (content == null)
                throw new ArgumentNullException("content");
    
            this.content = content;
            this.bufferOutput = bufferOutput;
            FileDownloadName = fileName;
        }
    
        /// <summary>
        /// Writes the file to the response.
        /// </summary>
        /// <param name="response">The response object.</param>
        protected override void WriteFile(System.Web.HttpResponseBase response)
        {
            response.Buffer = bufferOutput;
            content(response.OutputStream);
        }
    }
    

    The controller method would now be like this:

    public ActionResult Export(int id)
    {
        return new FileGeneratingResult(id + ".csv", "text/csv",
            stream => this.GenerateExportFile(id, stream));
    }
    
    public void GenerateExportFile(int id, Stream stream)
    {
        stream.Write(/**/);
    }
    

    Note that if buffering is turned off,

    stream.Write(/**/);
    

    becomes extremely slow. The solution is to use a BufferedStream. Doing so improved performance by approximately 100x in one case. See

    Unbuffered Output Very Slow

    0 讨论(0)
  • 2020-11-29 04:48

    Yes, you can write directly to the Response. After you're done, you can call CompleteRequest() and you shouldn't need to return anything.

    For example:

    // GET: /Test/Edit/5
    public ActionResult Edit(int id)
    {
    
        Response.Write("hi");
        HttpContext.ApplicationInstance.CompleteRequest();
    
        return View();     // does not execute!
    }
    
    0 讨论(0)
提交回复
热议问题