¿Alguien sabe cómo obtener el html generado de una vista dentro de una acción?
Es algo como esto:
public ActionResult Do()
{
var html = RenderView("hello", model);
...
}
Respuestas:
Utilizo un método estático en una clase que llamé. Utilities.Common
Le paso las vistas al cliente como propiedades de los objetos JSON constantemente, así que tuve la necesidad de representarlas en una cadena. Aqui tienes:
public static string RenderPartialViewToString(Controller controller, string viewName, object model)
{
controller.ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.ToString();
}
}
Esto funcionará tanto para vistas completas como para vistas parciales, simplemente cambie ViewEngines.Engines.FindPartialView
a ViewEngines.Engines.FindView
.
this
como argumento del controlador. RenderPartialViewToString(this, "index", viewModel)
. Creo que es una tontería que no haya una manera más fácil de simplemente invocar el motor de vista y recuperar una cadena, pero en ASP.NET el motor de vista necesita referencia a la instancia del controlador para compilar la vista. Ahora soy desarrollador de nodeJS y los motores de vista en el nodo son módulos completamente separados que puede invocar manualmente o con un marco MVC como express .
La respuesta aceptada por @Chev anterior es buena, pero quería representar el resultado de una acción específica , no solo una vista en particular .
Además, necesitaba poder pasar parámetros a esa acción en lugar de depender de inyectar un modelo.
Así que se me ocurrió mi propio método, que puse en la clase base de mis controladores (haciéndolo disponible para todos):
protected string RenderViewResultAsString(ViewResult viewResult)
{
using (var stringWriter = new StringWriter())
{
this.RenderViewResult(viewResult, stringWriter);
return stringWriter.ToString();
}
}
protected void RenderViewResult(ViewResult viewResult, TextWriter textWriter)
{
var viewEngineResult = this.ViewEngineCollection.FindView(
this.ControllerContext,
viewResult.ViewName,
viewResult.MasterName);
var view = viewEngineResult.View;
try
{
var viewContext = new ViewContext(
this.ControllerContext,
view,
this.ViewData,
this.TempData,
textWriter);
view.Render(viewContext, textWriter);
}
finally
{
viewEngineResult.ViewEngine.ReleaseView(this.ControllerContext, view);
}
}
Supongamos que tengo una acción llamada Foo
que toma un objeto modelo y algunos otros parámetros, que en conjunto influyen en la vista que se utilizará:
public ViewResult Foo(MyModel model, int bar)
{
if (bar == 1)
return this.View("Bar1");
else
return this.View("Bar2", model);
}
Ahora, si quiero obtener el resultado de llamar a la acción Foo
, simplemente puedo obtenerlo ViewResult
invocando el Foo
método y luego llamar RenderViewResultAsString
para obtener el texto HTML:
var viewResult = this.Foo(model, bar);
var html = this.RenderViewResultAsString(viewResult);
masterName
) que especificaría null. También recomiendo guardar y restaurar (después de renderizar) controller.ViewData.Model en caso de que se llame al método en la instancia del controlador actual y el modelo se haya asignado antes de esta llamada.