2012-08-16 208 views
7

我想在我的ASP.NET应用程序中创建一个手动触发的进程,并将一堆电子邮件发送给我的用户。由于此过程需要一段时间,我正在创建一个新线程来发送这些消息,并防止在我的Web应用程序中超时。 (我知道这是错误的情况下,应用程序池被回收或应用程序中有未处理的异常,但这是另一个主题)。ASP.NET MVC:新线程中的异常渲染视图

对于我正在做这样的事情:

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方法被调用。

我猜这与控制器上下文在新线程中不再有效的事实有关,但我不确定。

那么,解决这个问题的最好方法是什么?我有什么替代方案?

感谢

回答

5

我猜这是与事实控制器方面 是在新线程不再有效的事,但我不知道。

准确地说。

那么,最好的方法是什么?

从另一个进程发送电子邮件,而不是您的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部分)。

+1

看起来像使用RazorEngine的主要问题是,您无法访问MVC的HtmlHelper和部分模板分辨率,而无法自行滚动。 – crush 2016-04-12 18:39:27