2012-08-16 16 views
7

Desidero creare un processo nella mia applicazione ASP.NET che viene attivato manualmente e invierà un sacco di e-mail ai miei utenti. Poiché questo processo richiede un po 'di tempo, sto creando un nuovo thread per inviare questi messaggi e impedire di avere timeout nella mia app web. (So ​​che questo è soggetto ad errori nel caso in cui il pool di applicazioni venga riciclato o ci sia un'eccezione non gestita nell'app, ma questo è un altro argomento).ASP.NET MVC: visualizzazione rendering di eccezione nella nuova discussione

Per quel che sto facendo qualcosa di simile:

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

all'interno del processo in esecuzione lungo sto cercando di rendere la vista per l'e-mail HTML e inviarlo. Come questo:

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

Ora, so che il mio metodo renderView funziona bene da quando lo uso per il rendering di vista e-mail in altri luoghi. Il problema è quando cerco di eseguirlo in un nuovo thread come sto facendo qui. Questo è il mio metodo 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(); 
     } 
    } 

L'errore che sto ottenendo è:

Value does not fall within the expected range. 

Quando il metodo viewResult.View.Render viene chiamato.

Immagino che questo abbia a che fare con il fatto che il contesto del controller non è più valido nel nuovo thread, ma non ne sono sicuro.

Quindi, qual è il modo migliore per avvicinarsi a questo? Quali alternative ho?

Grazie

risposta

5

Sto indovinando questo ha a che fare con il fatto che il contesto di controllo non è più valido nel nuovo thread, ma non sono sicuro.

Precisamente.

Quindi, qual è il modo migliore per avvicinarsi a questo?

Invia e-mail da un altro processo, non dall'applicazione ASP.NET MVC.

Quali alternative ho?

Una possibilità è quella di utilizzare 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); 
    } 
} 

Si potrebbe anche checkout MvcMailer e inviare l'e-mail in modo asincrono (dare un'occhiata alla sezione Send Email Asynchronously del passo-passo-guida).

+1

Sembra che il problema principale con l'utilizzo di RazorEngine è che non si ottiene l'accesso a MVC HtmlHelper e alla risoluzione del modello parziale senza il rollover. – crush

Problemi correlati