ASP.NET MVC电子邮件

And*_*rew 13 c# email asp.net-mvc templates spark-view-engine

他们是使用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;
Run Code Online (Sandbox Code Playgroud)

上面的代码使用当前的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); 
Run Code Online (Sandbox Code Playgroud)

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

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

And*_*rew 11

这就是我想要的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


Chr*_*ris 8

为什么需要从视图中创建电子邮件?为什么不使用普通的旧模板文件?我一直这样做 - 我制作一个模板并使用城堡项目中的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);
Run Code Online (Sandbox Code Playgroud)

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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您根本不必干涉视图引擎,理论上如果需要,您可以使用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));
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*Led 7

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

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

这是我的扩展类,用于生成字符串视图.首先是标准视图引擎,第二个是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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有一个解决方案 - 使用Web表单引擎的解决方法 - 单个视图引擎 - Spark ;-) (2认同)