проблема со всеми вышеупомянутыми решениями заключается в том, что они не безопасны для потоков !.
что если вы хотите визуализировать вид из другого потока? (для электронной почты)
в этом случае ControllerContext больше не относится ни к этому Controller
для этих случаев я предлагаю следующее решение:
ThreadPool.QueueUserWorkItem(_ =>
{
var model = new TestMailModel() { Sender = "yakirmanor", Recipient = "yakirmanor@notrealmail.com", 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("yakirmanor@notrealmail.com", "subject", test1, "username", "password");
});
здесь вы можете видеть, как я вызываю метод TestMail в контроллере Mail, а также TestMail в текущем контроллере.
создать расширения
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();
}
}
чтобы использовать код, необходимый для добавления вашей модели и поддельного контроллера
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() { }
}
вид может выглядеть так:
@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>