ASP.NET MVC电子邮件

他们是使用ASP.NET MVC View生成电子邮件模板的解决方案,而无需跳过篮球。

让我详细说明跳过篮球。

var fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse); var oldContext = HttpContext.Current; HttpContext.Current = fakeContext; var html = new HtmlHelper(new ViewContext(fakeControllerContext, new FakeView(), viewDataDictionary, new TempDataDictionary()), new ViewPage()); html.RenderPartial(viewName, viewData, viewDataDictionary); HttpContext.Current = oldContext; 

上面的代码使用当前的HttpContext伪造一个新的Context并使用RenderPartial渲染页面,我们不应该这样做。

使用ControllerContext和.Render的另一个非常详细的解决方案:( IEmailTemplateService,Headers / Postback WorkAround ),但是用更多的代码做同样的事情。

另一方面,我正在寻找能够呈现View而不必POST / GET的东西,并生成一个简单的字符串,我可以通过我的电子邮件代码发送。 不会发生错误的事情,例如两次发布标题或伪造一些数据。

EX:

 //code which does not fire Render, RenderPartial... etc var email = emailFramework.Create(viewData, view); 

请参阅我的解决方案或点击此链接:

我的解决方案使用spark:(12/30/2009) ASP.NET MVC电子邮件模板解决方案

这就是我想要的ASP.NET MVC ViewEngine,但它在Spark中,只需按照右边的最新链接,

更新(12/30/2009)清洁版: ASP.NET MVC电子邮件模板解决方案


(11/16/2009)或者,Louis DeJardin控制台应用版本:

 using System; using Spark; using Spark.FileSystem; public class User { public int Id { get; set; } public string Name { get; set; } } public abstract class EmailView : AbstractSparkView { public User user { get; set; } } class Program { static void Main(string[] args) { // following are one-time steps // create engine var settings = new SparkSettings() .SetPageBaseType(typeof(EmailView)); var templates = new InMemoryViewFolder(); var engine = new SparkViewEngine(settings) { ViewFolder = templates }; // add templates templates.Add("sample.spark", @"Dear ${user.Name}, This is an email.Sincerely, Spark View Engine http://constanto.org/unsubscribe/${user.Id}"); // following are per-render steps // render template var descriptor = new SparkViewDescriptor() .AddTemplate("sample.spark"); var view = (EmailView)engine.CreateInstance(descriptor); view.user = new User { Id = 655321, Name = "Alex" }; view.RenderView(Console.Out); Console.ReadLine(); } } 

我决定使用这种方法,因为它似乎是一切正确,它:

  • 不使用任何HttpContext / ControllerContext或乱用路由数据!
  • 它可以实现页眉/页脚以允许模板!
  • 你可以使用循环,条件等…
  • 它干净,重量轻,特别是如果你打算完全移动到火花视图引擎!

请务必阅读这些post。 所有归功于Louis DeJardin看到他的教程:): 使用Spark作为通用模板引擎! ,重新访问电子邮件模板

为什么需要从视图中创建电子邮件? 为什么不使用普通的旧模板文件? 我一直这样做 – 我制作一个模板并使用城堡项目中的NVelocity引擎(不要与nvelocity VIEW引擎混淆)来渲染模板。

例:

 var nvEngine = new NVelocityEngine(); nvEngine.Context.Add("FullName", fullName); nvEngine.Context.Add("MallName", voucher.Mall.Name); nvEngine.Context.Add("ConfirmationCode", voucher.ConfirmationCode); nvEngine.Context.Add("BasePath", basePath); nvEngine.Context.Add("TermsLink", termsLink); nvEngine.Context.Add("LogoFilename", voucher.Mall.LogoFilename); var htmlTemplate = System.IO.File.ReadAllText( Request.MapPath("~/App_Data/Templates/Voucher.html")); var email = nvEngine.Render(htmlTemplate); 

NVelocityEngine类是我在Castle项目提供的NVelocity端口周围编写的包装器,如下所示:

 using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using NVelocity; using NVelocity.App; namespace MyProgram { ///  /// A wrapper for the NVelocity template processor ///  public class NVelocityEngine : VelocityEngine { Hashtable context = new Hashtable(); ///  /// A list of values to be merged with the template ///  public Hashtable Context { get { return context; } } ///  /// Default constructor ///  public NVelocityEngine() { base.Init(); } ///  /// Renders a template by merging it with the context items ///  public string Render(string template) { VelocityContext nvContext; nvContext = new VelocityContext(context); using (StringWriter writer = new StringWriter()) { this.Evaluate(nvContext, writer, "template", template); return writer.ToString(); } } } } 

通过这种方式,您根本不必干涉视图引擎,理论上如果您愿意,可以使用ASP.NET视图引擎将其链接,就像我在以下控制器方法中所做的那样:

 public ActionResult ViewVoucher(string e) { e = e.Replace(' ', '+'); var decryptedEmail = CryptoHelper.Decrypt(e); var voucher = Voucher.FindByEmail(decryptedEmail); if (voucher == null) return View("Error", new Exception("Voucher not found.")); var basePath = new Uri(Request.Url, Url.Content("~/")).ToString(); var termsLink = new Uri(Request.Url, Url.Action("TermsGC", "Legal")).ToString(); basePath = basePath.Substring(0, basePath.Length - 1); var fullName = voucher.FirstName; if (!string.IsNullOrEmpty(voucher.LastName)) fullName += " " + voucher.LastName; var nvEngine = new NVelocityEngine(); nvEngine.Context.Add("FullName", fullName); nvEngine.Context.Add("MallName", voucher.Mall.Name); nvEngine.Context.Add("ConfirmationCode", voucher.ConfirmationCode); nvEngine.Context.Add("BasePath", basePath); nvEngine.Context.Add("TermsLink", termsLink); nvEngine.Context.Add("LogoFilename", voucher.Mall.LogoFilename); var htmlTemplate = System.IO.File.ReadAllText( Request.MapPath("~/App_Data/Templates/Voucher.html")); return Content(nvEngine.Render(htmlTemplate)); } 

尝试使用spark view engine( http://www.sparkviewengine.com/ )。 它易于使用,比标准引擎更好,并且不需要伪造上下文。

您还可以使用此答案中的函数将视图渲染为字符串 ,但它需要伪造上下文。 这是标准视图引擎的工作方式,您无能为力。

这是我的扩展类,用于生成字符串视图。 首先是标准视图引擎,第二个是Spark:

 public static class ControllerHelper { /// Renders a view to string. public static string RenderViewToString(this Controller controller, string viewName, object viewData) { //Getting current response var response = HttpContext.Current.Response; //Flushing response.Flush(); //Finding rendered view var view = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName).View; //Creating view context var viewContext = new ViewContext(controller.ControllerContext, view, controller.ViewData, controller.TempData); //Since RenderView goes straight to HttpContext.Current, we have to filter and cut out our view var oldFilter = response.Filter; Stream filter = new MemoryStream(); ; try { response.Filter = filter; viewContext.View.Render(viewContext, null); response.Flush(); filter.Position = 0; var reader = new StreamReader(filter, response.ContentEncoding); return reader.ReadToEnd(); } finally { filter.Dispose(); response.Filter = oldFilter; } } /// Renders a view to string. public static string RenderSparkToString(this Controller controller, string viewName, object viewData) { var view = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName).View; //Creating view context var viewContext = new ViewContext(controller.ControllerContext, view, controller.ViewData, controller.TempData); var sb = new StringBuilder(); var writer = new StringWriter(sb); viewContext.View.Render(viewContext, writer); writer.Flush(); return sb.ToString(); } } 

如果你想要简单的文本替换,.NET有一些东西:

  ListDictionary replacements = new ListDictionary(); // Replace hard coded values with objects values replacements.Add("{USERNAME}", "NewUser"); replacements.Add("https://stackoverflow.com/questions/1730134/asp-net-mvc-email/{SITE_URL}", "http://yourwebsite.com"); replacements.Add("{SITE_NAME}", "My site's name"); string FromEmail= "from@yourwebsite.com"; string ToEmail = "newuser@gmail.com"; //Create MailDefinition MailDefinition md = new MailDefinition(); //specify the location of template md.BodyFileName = "~/Templates/Email/Welcome.txt"; md.IsBodyHtml = true; md.From = FromEmail; md.Subject = "Welcome to youwebsite.com "; System.Web.UI.Control ctrl = new System.Web.UI.Control { ID = "IDontKnowWhyThisIsRequiredButItWorks" }; MailMessage message = md.CreateMailMessage(ToEmail , replacements, ctrl); //Send the message SmtpClient client = new SmtpClient(); client.Send(message); 

和Welcome.txt文件

  Welcome - {SITE_NAME}

Thank you for registering at {SITE_NAME}

Your account is activated and ready to go!
To login, visit {SITE_NAME} and use the following credentials:
username: {USERNAME}
password: use the password you registered with

- {SITE_NAME} Team

同样,这仅适用于简单的字符串替换。 如果您计划通过电子邮件发送更多数据,则需要将其正确格式化然后替换它。

您可以考虑使用MvcMailer NuGet – 它可以满足您的需求并干净利落地完成任务。 请参阅此处的NuGet包和项目文档

希望能帮助到你!

我为LukLed的RenderSparkToString方法创建了一个重载,它允许你使用火花布局和你的视图:

 public static string RenderSparkToString(this Controller controller, string viewName, string masterName, object viewData) { var view = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, masterName).View; //Creating view context var viewContext = new ViewContext(controller.ControllerContext, view, controller.ViewData, controller.TempData); var sb = new StringBuilder(); var writer = new StringWriter(sb); viewContext.View.Render(viewContext, writer); writer.Flush(); return sb.ToString(); } 

我同意安德鲁的意见。 我希望有一种更简单的方法来使用Web表单视图引擎。

虽然这是一个有点旧的线程,但我鼓励你看一下MvcMailer NuGet包 – 它大大简化了整个过程,并使邮件表现得很好