簡體   English   中英

ASP.NET MVC電子郵件

[英]ASP.NET MVC Email

他們的解決方案是使用ASP.NET MVC視圖生成電子郵件模板,而不必跳過去。

讓我詳細說明一下。

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並為我生成一個可以通過我的Email代碼發送的簡單字符串的東西。 不會出錯的東西,例如兩次發布標題或偽造某些數據。

例如:

//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中,只需點擊下面的最新鏈接,

更新(2009/12/30)清潔版本: 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或弄亂路由數據!
  • 它可以實現頁眉/頁腳以允許模板!
  • 您可以使用循環,條件等...
  • 它整潔,重量輕,特別是如果您打算完全移動以激發View引擎!

請確保閱讀這些帖子。 值得一提的是Louis DeJardin,請參閱他的教程:): 將Spark用作通用模板引擎! ,重新訪問電子郵件模板

為什么需要從視圖創建電子郵件? 為什么不使用普通的舊模板文件? 我一直這樣做-我制作了一個模板,並使用了Castle項目中的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
{
    /// <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));
}

嘗試使用Spark View引擎( http://www.sparkviewengine.com/ )。 它易於使用,比標准引擎更好,並且不需要偽造上下文。

您也可以從此答案中使用function 將視圖呈現為字符串 ,但這需要偽造的上下文。 這是標准視圖引擎的工作方式,您對此無能為力。

這是我的擴展類,用於生成字符串視圖。 首先是標准視圖引擎,其次是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();
    }
}

如果您想要簡單的文本替換,.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

同樣,這僅適用於簡單的字符串替換。 如果您打算通過電子郵件發送更多數據,則需要正確設置其格式然后替換它。

您可以考慮使用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程序包-它大大簡化了整個過程並使郵件程序表現出良好的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM