2012-01-13 16 views
5

Estoy creando una aplicación que enviará correos electrónicos personalizados a los usuarios finales.Devolver ASP.NET MVC Ver como archivo HTML para usar en el correo electrónico Plantilla

He creado una plantilla HTML a partir de la cual se generarán los correos electrónicos.

que actualmente tiene la plantilla llena de etiquetas como marcadores de posición para el contenido personalizado ...

|Text-Placeholder| 

he estado volviendo el archivo HTML como una cadena a mi método CreateEMail:

string html = System.IO.File.ReadAllText(Server.MapPath("~/EmailTemplates/emailTemplate.html")); 

y a continuación, utilizando String.Replace para sustituir en el texto de encargo/contenido

html = html.Replace("|Name-Placeholder|", username); 

Tengo curiosidad por saber si hay un método que me permita construir la plantilla como un RazorView fuertemente tipificado como un modelo de vista que modelará el texto/contenido personalizado, y devolverá la vista como un archivo HTML o directamente como una cadena para pasar a la propiedad del cuerpo de mi instancia SMTPClient para enviar al usuario?

¿Alguien ha logrado algo así o similar?

+0

posible duplicado de [Renderizar una vista como una cadena] (http: //stackoverflow.com/questions/483091/render-a-view-as-a-string) – jrummell

+1

Los comentarios en el duplicado sugerido se refieren a ese método que no funciona en MVC 3 y "Mejores formas de lograr esto ahora" – stephen776

Respuesta

10

Tener un vistazo a estas bibliotecas:

Hay ActionMailer. Inspirado por el ActionMailer de Ruby.

ActionMailer.Net pretende ser una manera fácil y relativamente sencilla de enviar correos electrónicos desde su aplicación ASP.NET MVC. El concepto es muy simple. Prestamos HTML utilizando algunos motores de vista bastante atractivos, entonces ¿por qué no podemos hacer lo mismo para el correo electrónico?

http://nuget.org/packages/ActionMailer

soporta varios motores de vista, creo, la maquinilla de afeitar incluye por supuesto. Y le permite pasar un modelo a la vista. Ver: https://bitbucket.org/swaj/actionmailer.net/wiki/Home

El código:

public class MailController : MailerBase 
{ 
    public EmailResult VerificationEmail(User model) 
    { 
     To.Add(model.EmailAddress); 
     From = "[email protected]"; 
     Subject = "Welcome to My Cool Site!"; 
     return Email("VerificationEmail", model); 
    } 
} 

La vista:

@using ActionMailer.Net 
@model User 
@{ 
    Layout = null; 
} 
Welcome to My Cool Site, @Model.FirstName. We need you to verify your email. 
Click this nifty link to get verified! 

También hay otra biblioteca:

MvcMailer le permite utilizar sus MVC Vistas para conseguir espectaculares correos electrónicos

http://nuget.org/packages/MvcMailer
https://github.com/smsohan/MvcMailer

+0

Me alegro de que haya ayudado. ¡Me equivoqué un poco con los enlaces y las descripciones! Editó la respuesta ahora. – gideon

0

puede utilizar este helper con el fin de despojar el código HTML de una vista. El método también acepta un modelo, la vista se procesa mediante programación y su resultado se devuelve como una cadena.Más mineral menos el mismo concepto de la LoadControl in Asp.net:

public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData) 
{ 
    var viewEngineResult = ViewEngines.Engines.FindPartialView(context, partialViewName); 

    if (viewEngineResult.View != null) 
    { 
     var stringBuilder = new StringBuilder(); 
     using (var stringWriter = new StringWriter(stringBuilder)) 
     { 
      using (var output = new HtmlTextWriter(stringWriter)) 
      { 
       ViewContext viewContext = new ViewContext(context, viewEngineResult.View, viewData, tempData, output); 
       viewEngineResult.View.Render(viewContext, output); 
      } 
     } 

     return stringBuilder.ToString(); 
    } 

    //return string.Empty; 
    throw new FileNotFoundException("The view cannot be found", partialViewName); 
} 

Aquí es donde el contenido de la vista se recupera

//The welcome email is in the Shared/Email folder 
string partialViewHtml = EmailHelpers.RenderPartialToString(this.ControllerContext, "Email/Welcome", new ViewDataDictionary(modelForPartialView), new TempDataDictionary()); 
0

el problema con todas las soluciones anteriores son que no es seguro para subprocesos !.

¿Qué sucede si desea representar la vista desde un hilo diferente? (Por correo electrónico)
en ese caso el ControllerContext ya no es relevante ni el este del controlador

para aquellos casos sugiero la siguiente solución:

ThreadPool.QueueUserWorkItem(_ => 
{ 
    var model = new TestMailModel() { Sender = "yakirmanor", Recipient = "[email protected]", Description = "some desc" }; 
    string test1 = ControllerExtensions.RenderView("Mail", "TestMail", model); 
    string test2 = this.RenderView("TestMail", model); 
    string test3 = this.RenderView(model); 
    // now send the mail 
    //MailHelper.SendEmail("[email protected]", "subject", test1, "username", "password"); 
}); 

aquí se puede ver que me llama la Testmail método en el controlador de correo y también el TestMail en el controlador actual.
para crear el extansions

public static class ControllerExtensions 
{ 
    public static string RenderView(this Controller controller, object model) 
    { 
     string viewName = controller.ControllerContext.RouteData.Values["action"].ToString(); 
     string controllerName = controller.ControllerContext.RouteData.Values["controller"].ToString(); 
     return RenderView(controllerName, viewName, model); 
    } 

    public static string RenderView(this Controller controller, string viewName, object model) 
    { 
     string controllerName = controller.ControllerContext.RouteData.Values["controller"].ToString(); 
     return RenderView(controllerName, viewName, model); 
    } 

    public static string RenderView(string controllerName, string viewName, object viewData) 
    { 
     //Create memory writer 
     var writer = new StringWriter(); 

     var routeData = new RouteData(); 
     routeData.Values.Add("controller", controllerName); 

     //Create fake http context to render the view 
     var fakeRequest = new HttpRequest(null, "http://tempuri.org", null); 
     var fakeResponse = new HttpResponse(null); 
     var fakeContext = new HttpContext(fakeRequest, fakeResponse); 
     var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), routeData, new FakeController()); 

     var razorViewEngine = new RazorViewEngine(); 
     var razorViewResult = razorViewEngine.FindView(fakeControllerContext,viewName,"",false); 

     var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer); 
     razorViewResult.View.Render(viewContext, writer); 

     return writer.ToString(); 
    } 
} 

utilizar el código es necesario agregar su modelo y el controlador falsa

public class TestMailModel 
{ 
    public string Sender { get; set; } 
    public string Recipient { get; set; } 
    public string Description { get; set; } 
} 

class FakeController : ControllerBase 
{ 
    protected override void ExecuteCore() { } 
} 

la vista podría parecer así:

@model Phytech.PhyToWeb.Controllers.TestMailModel 
@{ 
Layout = null; 
} 
<table cellpadding="8" cellspacing="0" style="width: 100%!important; background: #ffffff; margin: 0; padding: 0" border="0"> 
    <tbody><tr><td valign="top"> 
    Hi @Model.Recipient youve got mail from @Model.Sender about @Model.Description 
    </td></tr></tbody> 
</table> 
0

como pequeña sugerencia, en lugar de marcadores de posición, usa recursos. usted crea un archivo de recursos, por ejemplo, en su directorio ~/Content llamado EMail.resx y agrega sus tokens a él. en la vista puede referirse a ellos de esta manera @EMail.Name y @EMail.Address. el beneficio es que si mañana necesita enviar el correo en francés, crea un EMail.fr.resx con los mismos tokens y ha terminado

Cuestiones relacionadas