代码之家  ›  专栏  ›  技术社区  ›  Andrew

ASP。NET MVC电子邮件

  •  13
  • Andrew  · 技术社区  · 16 年前

    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,并使用RenderPart渲染页面,我们不应该这样做。

    ( IEmailTemplateService, Headers/Postback WorkAround

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

    ASP.NET MVC Email Template Solution

    7 回复  |  直到 14 年前
        1
  •  11
  •   Andrew    16 年前

    这就是我想要的ASP。NET MVC ViewEngine可以做,但它在Spark中,只需点击下面的最新链接,

    更新(12/30/2009)清洁版本: ASP.NET MVC Email Template Solution


    (11/16/2009)

    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();
        }
    }
    

    • 它可以实现页眉/页脚以允许模板!
    • 你可以使用循环、条件句等。。。

    请务必阅读这些帖子。Louis DeJardin的所有功劳请参阅他的教程:): Using Spark as a general purpose template engine! , Email Templates Revisited

        2
  •  8
  •   Chris    16 年前

    为什么需要从视图创建电子邮件?为什么不使用普通的旧模板文件?我经常这样做——我制作了一个模板,并使用城堡项目中的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
    {
        /// <summary>
        /// A wrapper for the NVelocity template processor
        /// </summary>
        public class NVelocityEngine : VelocityEngine
        {
            Hashtable context = new Hashtable();
    
            /// <summary>
            /// A list of values to be merged with the template
            /// </summary>
            public Hashtable Context
            {
                get { return context; }
            }
    
            /// <summary>
            /// Default constructor
            /// </summary>
            public NVelocityEngine()
            {
                base.Init();
            }
    
            /// <summary>
            /// Renders a template by merging it with the context items
            /// </summary>
            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));
    }
    
        3
  •  7
  •   Community Mohan Dere    9 年前

    尝试使用火花视图引擎( http://www.sparkviewengine.com/

    您还可以使用此答案中的函数 Render a view as a string ,但这需要伪造上下文。这是标准视图引擎的工作方式,您对此无能为力。

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

    public static class ControllerHelper
    {
        /// <summary>Renders a view to string.</summary>
        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;
            } 
        }
    
        /// <summary>Renders a view to string.</summary>
        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();
        }
    }
    
        4
  •  4
  •   Omar    16 年前

    如果你想要简单的文本替换。NET有这样的功能:

            ListDictionary replacements = new ListDictionary();
    
            // Replace hard coded values with objects values
            replacements.Add("{USERNAME}", "NewUser");            
            replacements.Add("{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}<br />
        <br />
        Thank you for registering at {SITE_NAME}<br />
        <br />
        Your account is activated and ready to go! <br />
        To login, visit <a href="{SITE_URL}">{SITE_NAME}</a> and use the following credentials:
        <br />
        username: <b>{USERNAME}</b><br />
        password: use the password you registered with
        <br />
        <br />
    
        - {SITE_NAME} Team
    

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

        5
  •  3
  •   Sohan    15 年前

    你可以考虑使用MvcMailer NuGet——它只做你想要的事情,而且做得很干净。查看NuGet包 here 和那个 project documentation

    希望它能有所帮助!

        6
  •  1
  •   beckelmw    16 年前

    我为LukLed的RenderSparkToString方法创建了一个重载,允许您在视图中使用spark布局:

    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();
    }
    

        7
  •  0
  •   Sohan    15 年前