简体   繁体   English

ASP.NET MVC:新线程中的异常呈现视图

[英]ASP.NET MVC: Exception rendering view in new thread

I want to create a process in my ASP.NET application that I trigger manually and will send a bunch of emails to my users. 我想在我的ASP.NET应用程序中创建一个手动触发的进程,并将向用户发送一堆电子邮件。 Since this process takes a while I am creating a new thread to send these messages and prevent having timeouts in my web app. 由于此过程需要一段时间,因此我创建了一个新线程来发送这些消息并防止在我的Web应用程序中超时。 (I know this is error prone in case the app pool is recycled or there's an unhandled exception in the app, but that's another subject). (我知道如果应用程序池被回收或应用程序中存在未处理的异常,这是容易出错的,但这是另一个主题)。

For that I'm doing something like this: 为此,我正在做这样的事情:

public ActionResult SendMessages()
{
  Task.Factory.StartNew(() => { SendMessagesLongRunningProcess(); });
  return View();
}

inside the long running process I'm trying to render the view for the HTML email and send it. 在长时间运行的过程中,我正在尝试呈现HTML电子邮件的视图并发送它。 Like this: 像这样:

private void SendMessagesLongRunningProcess()
{
  var users = GetUsers();
  foreach (var user in users)
  {
    string message = RenderView("EmailMessage", user);
    SendEmail(user.email, message);
  }
}

Now, I know that my RenderView method works just fine since I use it to render email views in other places. 现在,我知道我的RenderView方法工作正常,因为我用它来渲染其他地方的电子邮件视图。 The problem is when I try to execute it in a new thread as I'm doing here. 问题是当我尝试在新线程中执行它时,就像我在这里所做的那样。 This is my RenderView method: 这是我的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();
        }
    }

The error I'm getting is: 我得到的错误是:

Value does not fall within the expected range.

When the viewResult.View.Render method is called. 调用viewResult.View.Render方法时。

I'm guessing this has to do with the fact that the controller context is no longer valid in the new thread, but I'm not sure. 我猜这与控制器上下文在新线程中不再有效的事实有关,但我不确定。

So, what is the best way to approach this? 那么,解决这个问题的最佳方法是什么? What alternatives do I have? 我有什么替代品?

Thanks 谢谢

I'm guessing this has to do with the fact that the controller context is no longer valid in the new thread, but I'm not sure. 我猜这与控制器上下文在新线程中不再有效的事实有关,但我不确定。

Precisely. 正是。

So, what is the best way to approach this? 那么,解决这个问题的最佳方法是什么?

Send emails from another process, not your ASP.NET MVC application. 从其他进程发送电子邮件,而不是ASP.NET MVC应用程序。

What alternatives do I have? 我有什么替代品?

One possibility is to use RazorEngine : 一种可能性是使用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);
    }
}

You might also checkout MvcMailer and send the email asynchronously (take a look at the Send Email Asynchronously section of the step-by-step-guide). 您也可以签出MvcMailer并异步发送电子邮件(请查看逐步指南的“ Send Email Asynchronously部分)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM