Reputation: 2046
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
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