我想在我的ASP.NET应用程序中创建一个手动触发的进程,并将向用户发送一堆电子邮件。由于此过程需要一段时间,因此我创建了一个新线程来发送这些消息并防止在我的Web应用程序中超时。 (我知道如果应用程序池被回收或应用程序中存在未处理的异常,这很容易出错,但这是另一个主题。)
为此,我正在做这样的事情:
public ActionResult SendMessages()
{
Task.Factory.StartNew(() => { SendMessagesLongRunningProcess(); });
return View();
}
在长时间运行的进程中,我正在尝试呈现HTML电子邮件的视图并发送它。像这样:
private void SendMessagesLongRunningProcess()
{
var users = GetUsers();
foreach (var user in users)
{
string message = RenderView("EmailMessage", user);
SendEmail(user.email, message);
}
}
现在,我知道我的RenderView方法工作得很好,因为我用它来渲染其他地方的电子邮件视图。问题是当我尝试在新线程中执行它时,就像我在这里所做的那样。 这是我的RenderView方法:
public string RenderView(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
我得到的错误是:
Value does not fall within the expected range.
调用viewResult.View.Render方法时。
我猜这与控制器上下文在新线程中不再有效这一事实有关,但我不确定。
那么,解决这个问题的最佳方法是什么?我有哪些替代方案?
由于
答案 0 :(得分:6)
我猜这与控制器上下文的事实有关 在新帖子中不再有效,但我不确定。
正。
那么,解决这个问题的最佳方法是什么?
从其他进程发送电子邮件,而不是ASP.NET MVC应用程序。
我有哪些替代方案?
一种可能性是使用RazorEngine
:
private void SendMessagesLongRunningProcess()
{
var users = GetUsers();
foreach (var user in users)
{
string view = Server.MapPath("~/Views/MailTemplates/SomeTemplate.cshtml");
string template = System.IO.File.ReadAllText(view);
string message = Razor.Parse(template, user);
SendEmail(user.email, message);
}
}
您也可以结帐MvcMailer
并异步发送电子邮件(请查看分步指南的Send Email Asynchronously
部分。)