Steve
Steve

Reputation: 2046

Mvc Render Action/Partial to Response Output

Although @Html.RenderPartial calls write and returns void, it is still writing to a StringWriter/StringBuilder. Is there a way to render directly to the ResponseStream?

Can this be done with a custom IViewEngine that implements render like PdfView to directly output to the ResponseStream?

ADDITION

ViewResultBase.ExecuteResult shows the ViewContext being built with Response.Output, but debugger shows ViewContext.Writer as a StringWriter

Both of these approaches results in a StringWriter

return PartialView("view", Model)
// or
PartialView("view", Model).ExecuteResult(ControllerContext)

EDIT

It appears that System.Web.WebPages.WebPageBase ExecutePageHeirarchy pushes a temp StringWriter onto the context stack, so I'm not sure if this can be bypassed

IN SUMMARY

RenderPartial, RenderAction do not directly output to the Response.Stream, none of Razor Views will

SOLUTION

It was the new WebPages/Razor rendering engine that wraps everything with a StringWriter to a StringBuilder. The solution was to change my page to use the WebFormViewEngine which does not apply this wrapping.

Upvotes: 5

Views: 806

Answers (1)

Jean-Michel Gaud
Jean-Michel Gaud

Reputation: 303

This below method illustrates one way achieving the outcome you are looking for:

// <summary>
// An extension methods for rendering a model/view into a stream
// </summary>
// <param name="myModel">The model you are trying render to a stream</param>
// <param name="controllerBase">This will come from your executing action</param>
// <returns></returns>
        public static Stream GetStream(CustomModel myModel, ControllerBase controllerBase)
        {
            //we will return this stream
            MemoryStream stream = new MemoryStream();

            //you can add variables to the view data
            controllerBase.ViewData["ViewDataVariable1"] = true;

            //set your model
            controllerBase.ViewData.Model = myModel;

            //The example uses the UTF-8 encoding, you should change that if you are using some other encoding.
            //write to a stream
            using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
            {
                using (var sw = new StringWriter())
                {
                    //render the view  ~/Views/Shared/_FeedbackMessage.cshtml (can be passed in as a parameter if you want to make it super generic)
                    var viewResult = ViewEngines.Engines.FindPartialView(controllerBase.ControllerContext, "_FeedbackMessage");

                    //create a new view context
                    var viewContext = new ViewContext(controllerBase.ControllerContext, viewResult.View, controllerBase.ViewData, controllerBase.TempData, sw);

                    //Render the viewengine and let razor do its magic
                    viewResult.View.Render(viewContext, sw);    
                    viewResult.ViewEngine.ReleaseView(controllerBase.ControllerContext, viewResult.View);

                    //get StringBuilder from StringWriter sw and write into the stream writer
                    //you could simply return the StringWriter here if that is what you were interested in doing
                    writer.Write(sw.GetStringBuilder().ToString());

                    writer.Flush();

                    stream.Position = 0;
                }

            }

            //return the stream from the above process
            return stream;
        }

Upvotes: 0

Related Questions