Render View programmatically in a line

I would like to get the html code that will generate the view in a string, modify it in my controller, and then add it to my JsonResult.

I found code that will do what I'm talking about from partial. I would like to do this from an aspx view though.

- Additional explanation:

Say I have a Frame.aspx page that / Controller / Frame will return

I would like to get my hand from the answer before this so that I can wrap it with jsonp. I don’t want to edit the result of returning to the code every time, so I want to programmatically download the file.

/ Controller / Frame returns the contents of Frame.aspx: <html><body>hello</body></html>

Say there is a function that displays a view in a row builder

 StringBuilder sb = new StringBuilder(); RenderView(sb, "Frame"); 

now take sb and wrap it with jsonp:

 public JsonResult Frame(string callback) { StringBuilder sb = new StringBuilder(); RenderView(sb, "Frame"); return new JsonResult { Data = "(function() { " + callback + "(" + clientResponse + "); })();" , JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } 
+6
c # asp.net-mvc asp.net-mvc-2
source share
3 answers

It works like a charm (got it through SO).

I use it as follows:

 public class OfferController : Controller { [HttpPost] public JsonResult EditForm(int Id) { var model = Mapper.Map<Offer, OfferEditModel>(_repo.GetOffer(Id)); return Json(new { status = "ok", partial = this.RenderPartialViewToString("Edit", model) }); } } public static partial class ControllerExtensions { public static string RenderPartialViewToString(this ControllerBase controller, string partialPath, object model) { if (string.IsNullOrEmpty(partialPath)) partialPath = controller.ControllerContext.RouteData.GetRequiredString("action"); controller.ViewData.Model = model; using (StringWriter sw = new StringWriter()) { ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialPath); ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw); // copy model state items to the html helper foreach (var item in viewContext.Controller.ViewData.ModelState) if (!viewContext.ViewData.ModelState.Keys.Contains(item.Key)) { viewContext.ViewData.ModelState.Add(item); } viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } } } 
+19
source share

Mike Hadlow wrote about the CaptureActionHtml () function that does this. I used it to compose larger reports from smaller, more manageable reports, and then passed them on.

http://mikehadlow.blogspot.com/2008/06/mvc-framework-capturing-output-of-view_05.html

 using System; using System.IO; using System.Web; using System.Web.Mvc; namespace Suteki.Common.Extensions { public static class ControllerExtensions { /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The controller</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this TController controller, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(controller, null, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The controller</param> /// <param name="masterPageName">The master page to use for the view</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this TController controller, string masterPageName, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(controller, masterPageName, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The current controller</param> /// <param name="targetController">The controller which has the action to execute</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this Controller controller, TController targetController, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(targetController, null, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The current controller</param> /// <param name="targetController">The controller which has the action to execute</param> /// <param name="masterPageName">The name of the master page for the view</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this Controller controller, TController targetController, string masterPageName, Func<TController, ViewResult> action) where TController : Controller { if (controller == null) { throw new ArgumentNullException("controller"); } if (targetController == null) { throw new ArgumentNullException("targetController"); } if (action == null) { throw new ArgumentNullException("action"); } // pass the current controller context to orderController var controllerContext = controller.ControllerContext; targetController.ControllerContext = controllerContext; // replace the current context with a new context that writes to a string writer var existingContext = System.Web.HttpContext.Current; var writer = new StringWriter(); var response = new HttpResponse(writer); var context = new HttpContext(existingContext.Request, response) {User = existingContext.User}; System.Web.HttpContext.Current = context; // execute the action var viewResult = action(targetController); // change the master page name if (masterPageName != null) { viewResult.MasterName = masterPageName; } // we have to set the controller route value to the name of the controller we want to execute // because the ViewLocator class uses this to find the correct view var oldController = controllerContext.RouteData.Values["controller"]; controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", ""); // execute the result viewResult.ExecuteResult(controllerContext); // restore the old route data controllerContext.RouteData.Values["controller"] = oldController; // restore the old context System.Web.HttpContext.Current = existingContext; return writer.ToString(); } } } 
0
source share

Here's another way to get around views in MVC 2.0 and> net 4.0. I just added a few lines of code to the original Andrews content.

  public static class ControllerExtensions { /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The controller</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this TController controller, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(controller, null, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The controller</param> /// <param name="masterPageName">The master page to use for the view</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this TController controller, string masterPageName, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(controller, masterPageName, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The current controller</param> /// <param name="targetController">The controller which has the action to execute</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> public static string CaptureActionHtml<TController>( this Controller controller, TController targetController, Func<TController, ViewResult> action) where TController : Controller { return controller.CaptureActionHtml(targetController, null, action); } /// <summary> /// Captures the HTML output by a controller action that returns a ViewResult /// </summary> /// <typeparam name="TController">The type of controller to execute the action on</typeparam> /// <param name="controller">The current controller</param> /// <param name="targetController">The controller which has the action to execute</param> /// <param name="masterPageName">The name of the master page for the view</param> /// <param name="action">The action to execute</param> /// <returns>The HTML output from the view</returns> /// public static string CaptureActionHtml<TController>(this Controller controller, TController targetController, string masterPageName, Func<TController, ViewResult> action) where TController : Controller { if (controller == null) { throw new ArgumentNullException("controller"); } if (targetController == null) { throw new ArgumentNullException("targetController"); } if (action == null) { throw new ArgumentNullException("action"); } // pass the current controller context to orderController var controllerContext = controller.ControllerContext; targetController.ControllerContext = controllerContext; // replace the current context with a new context that writes to a string writer var existingContext = HttpContext.Current; var writer = new StringWriter(); var response = new HttpResponse(writer); var context = new HttpContext(existingContext.Request, response) { User = existingContext.User }; HttpContext.Current = context; // execute the action var viewResult = action(targetController); // change the master page name if (masterPageName != null) { viewResult.MasterName = masterPageName; } // we have to set the controller route value to the name of the controller we want to execute // because the ViewLocator class uses this to find the correct view var oldController = controllerContext.RouteData.Values["controller"]; controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", ""); // execute the result viewResult.ExecuteResult(controllerContext); StringWriter sw = new StringWriter(); var xx = targetController.TempData["pdf"]; //var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(targetController.ViewData.Model), new TempDataDictionary(), sw); var viewContext = new ViewContext(controllerContext, viewResult.View, viewResult.ViewData, new TempDataDictionary(), sw); viewResult.View.Render(viewContext, HttpContext.Current.Response.Output); response.Flush(); // restore the old route data controllerContext.RouteData.Values["controller"] = oldController; // restore the old context HttpContext.Current = existingContext; return sw.ToString(); } } } 

Hooray!!

0
source share

All Articles