Ich habe es getan. Mit viel Schmerz.
Zuerst müssen wir Controller ohne Kontext initiieren. Dazu verwende ich Rick Strahl-Methode namens CreateController
public static T CreateController<T>(RouteData routeData = null)
where T : Controller, new()
{
// create a disconnected controller instance
T controller = new T();
// get context wrapper from HttpContext if available
HttpContextBase wrapper = null;
if (HttpContext.Current != null)
wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
else
throw new InvalidOperationException(
"Can't create Controller Context if no active HttpContext instance is available.");
if (routeData == null)
routeData = new RouteData();
// add the controller routing if not existing
if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
routeData.Values.Add("controller", controller.GetType().Name
.ToLower()
.Replace("controller", ""));
controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
return controller;
}
Quelle: http://weblog.west-wind.com/posts/2013/Jul/15/Rendering-ASPNET-MVC-Razor-Views-outside-of-MVC-revisited
Aber wenn Sie diese Methode aufrufen, wenn Httpcontext es wird Ausnahme auslösen. Um zu verhindern, dass ich falschen Kontext mit diesem Code initiiere: https://stackoverflow.com/a/19709225/1850880.
Dann initiiere ich Controller und Call-Aktion. Ergebnis dieser Aktion enthält viewData mit allen Daten, die von Aktion übergeben wurden. Wir können es mit Reflektion (wie ein Ninja) bekommen. Und dann können wir Ansicht auf String mit übergebenem Modell rendern.
var controller = CreateController<ControllerName>();
var result = controller.ActionName(param1, param2);
object viewData = result.GetType().GetProperty("ViewData").GetValue(result);
object values = viewData.GetType().GetProperty("Values").GetValue(viewData);
var str = ec.RenderRazorViewToString("ViewName", values);
return str;
Diese Methode im Hinblick auf String-Render:
public static string RenderRazorViewToString(this Controller controller, string viewName, object model)
{
controller.ViewData.Model = model;
controller.ViewBag.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Sieht aus wie es nicht der beste Weg ist, aber es funktioniert. Also, wenn Sie irgendwelche Ideen haben, schreiben Sie unbedingt.
Wenn Sie diese E-Mails verwenden Sie können wie in etwas aussehen wollen [MvcMailer] (https://www.nuget.org/packages/MvcMailer), die ziemlich genau das tut, was Sie suchen. Ich hatte in der Vergangenheit Erfolg damit und es ist einfach zu implementieren. – zgood