我在我的MVC 5项目中添加了一个简报功能,用于向所有订阅用户发送构建的邮件
我从一个动作public async Task<NewsletterLogResult> SendNewsletters(int? id = null, ControllerContext ControllerContext = null)
中调用了public async Task<ActionResult>SendMail(int id)
的课程
SendNewsletters
实现Viewrenderer
,类似cBody = ViewRenderer.RenderPartialView(ViewRenderer.TemplatePath + "Newsletters/" + record.Newsletter_Template + "Body.cshtml", record, ControllerContext);
public class ViewRenderer
{
protected ControllerContext Context { get; set; }
public const string TemplatePath = "~/Views/Templates/";
public ViewRenderer(ControllerContext controllerContext = null)
{
// Create a known controller from HttpContext if no context is passed
if (controllerContext == null)
{
if (HttpContext.Current != null)
controllerContext = CreateController<EmptyController>().ControllerContext;
else
throw new InvalidOperationException(
"ViewRenderer must run in the context of an ASP.NET Application and requires HttpContext.Current to be present.");
}
Context = controllerContext;
}
public string RenderViewToString(string viewPath, object model = null)
{
return RenderViewToStringInternal(viewPath, model, false);
}
public void RenderView(string viewPath, object model, TextWriter writer)
{
RenderViewToWriterInternal(viewPath, writer, model, false);
}
public string RenderPartialViewToString(string viewPath, object model = null)
{
return RenderViewToStringInternal(viewPath, model, true);
}
public void RenderPartialView(string viewPath, object model, TextWriter writer)
{
RenderViewToWriterInternal(viewPath, writer, model, true);
}
public static string RenderView(string viewPath, object model = null,
ControllerContext controllerContext = null)
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
return renderer.RenderViewToString(viewPath, model);
}
public static void RenderView(string viewPath, TextWriter writer, object model,
ControllerContext controllerContext)
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
renderer.RenderView(viewPath, model, writer);
}
public static string RenderView(string viewPath, object model,
ControllerContext controllerContext,
out string errorMessage)
{
errorMessage = null;
try
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
return renderer.RenderViewToString(viewPath, model);
}
catch (Exception ex)
{
errorMessage = ex.GetBaseException().Message;
}
return null;
}
public static void RenderView(string viewPath, object model, TextWriter writer,
ControllerContext controllerContext,
out string errorMessage)
{
errorMessage = null;
try
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
renderer.RenderView(viewPath, model, writer);
}
catch (Exception ex)
{
errorMessage = ex.GetBaseException().Message;
}
}
public static string RenderPartialView(string viewPath, object model = null,
ControllerContext controllerContext = null)
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
return renderer.RenderPartialViewToString(viewPath, model);
}
public static void RenderPartialView(string viewPath, TextWriter writer, object model = null,
ControllerContext controllerContext = null)
{
ViewRenderer renderer = new ViewRenderer(controllerContext);
renderer.RenderPartialView(viewPath, model, writer);
}
protected void RenderViewToWriterInternal(string viewPath, TextWriter writer, object model = null, bool partial = false)
{
// first find the ViewEngine for this view
ViewEngineResult viewEngineResult = null;
if (partial)
viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath);
else
viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, null);
if (viewEngineResult == null)
throw new FileNotFoundException();
// get the view and attach the model to view data
var view = viewEngineResult.View;
Context.Controller.ViewData.Model = model;
var ctx = new ViewContext(Context, view,
Context.Controller.ViewData,
Context.Controller.TempData,
writer);
view.Render(ctx, writer);
}
private string RenderViewToStringInternal(string viewPath, object model,
bool partial = false)
{
// first find the ViewEngine for this view
ViewEngineResult viewEngineResult = null;
if (partial)
viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath);
else
viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, null);
if (viewEngineResult == null || viewEngineResult.View == null)
{
//throw new FileNotFoundException(Resources.ViewCouldNotBeFound);
throw new Exception("Can't find view.");
}
// get the view and attach the model to view data
var view = viewEngineResult.View;
Context.Controller.ViewData.Model = model;
string result = null;
using (var sw = new StringWriter())
{
var ctx = new ViewContext(Context,
view,
Context.Controller.ViewData,
Context.Controller.TempData,
sw);
view.Render(ctx, sw);
result = sw.ToString();
}
return result;
}
public static T CreateController<T>(RouteData routeData = null, params object[] parameters)
where T : Controller, new()
{
// create a disconnected controller instance
T controller = (T)Activator.CreateInstance(typeof(T), parameters);
// 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;
}
}
public class EmptyController : Controller
{
}
这在MVC中完美运行
就像从Web应用程序运行通讯发送任务不是一个好习惯,我想在Windows服务中实现此功能。为了便于我在 Consoleapp 中测试,请从此处SendNewsletters
进行调用。
但是在Consolapp中,就像在WIndowsService中一样,我没有 HttpContext ,因此,可以创建一个假的HttpContext,最好能访问MVC路由(我的razor视图实现了路由助手,{{1} })?
答案 0 :(得分:0)
我解决了存储在数据库中的这个问题,另外还有viewrendered的结果。此信息在MVC应用程序中处理,因此我不需要HttpContext或任何路由。