el problema con todas las soluciones anteriores son que no es seguro para subprocesos !.
¿Qué sucede si desea representar la vista desde un hilo diferente? (Por correo electrónico)
en ese caso el ControllerContext ya no es relevante ni el este del controlador
para aquellos casos sugiero la siguiente solución:
ThreadPool.QueueUserWorkItem(_ =>
{
var model = new TestMailModel() { Sender = "yakirmanor", Recipient = "[email protected]", Description = "some desc" };
string test1 = ControllerExtensions.RenderView("Mail", "TestMail", model);
string test2 = this.RenderView("TestMail", model);
string test3 = this.RenderView(model);
// now send the mail
//MailHelper.SendEmail("[email protected]", "subject", test1, "username", "password");
});
aquí se puede ver que me llama la Testmail método en el controlador de correo y también el TestMail en el controlador actual.
para crear el extansions
public static class ControllerExtensions
{
public static string RenderView(this Controller controller, object model)
{
string viewName = controller.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = controller.ControllerContext.RouteData.Values["controller"].ToString();
return RenderView(controllerName, viewName, model);
}
public static string RenderView(this Controller controller, string viewName, object model)
{
string controllerName = controller.ControllerContext.RouteData.Values["controller"].ToString();
return RenderView(controllerName, viewName, model);
}
public static string RenderView(string controllerName, string viewName, object viewData)
{
//Create memory writer
var writer = new StringWriter();
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
//Create fake http context to render the view
var fakeRequest = new HttpRequest(null, "http://tempuri.org", null);
var fakeResponse = new HttpResponse(null);
var fakeContext = new HttpContext(fakeRequest, fakeResponse);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext,viewName,"",false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
utilizar el código es necesario agregar su modelo y el controlador falsa
public class TestMailModel
{
public string Sender { get; set; }
public string Recipient { get; set; }
public string Description { get; set; }
}
class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
}
la vista podría parecer así:
@model Phytech.PhyToWeb.Controllers.TestMailModel
@{
Layout = null;
}
<table cellpadding="8" cellspacing="0" style="width: 100%!important; background: #ffffff; margin: 0; padding: 0" border="0">
<tbody><tr><td valign="top">
Hi @Model.Recipient youve got mail from @Model.Sender about @Model.Description
</td></tr></tbody>
</table>
posible duplicado de [Renderizar una vista como una cadena] (http: //stackoverflow.com/questions/483091/render-a-view-as-a-string) – jrummell
Los comentarios en el duplicado sugerido se refieren a ese método que no funciona en MVC 3 y "Mejores formas de lograr esto ahora" – stephen776