C# ASP.NET MVC电子邮件
他们的解决方案是使用ASP.NET MVC视图生成电子邮件模板,而无需跳转C# ASP.NET MVC电子邮件,c#,asp.net-mvc,email,templates,spark-view-engine,C#,Asp.net Mvc,Email,Templates,Spark View Engine,他们的解决方案是使用ASP.NET MVC视图生成电子邮件模板,而无需跳转 var fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse); var oldContext = HttpContext.Current; HttpContext.Current = fakeContext; var html = new HtmlHelper(new ViewContext(fakeControllerConte
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;
让我来详细说明一下跳环
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来伪造新的上下文,并使用RenderPartial呈现页面,我们不应该这样做
使用ControllerContext和.Render的另一个非常详细的解决方案:
()但是用更多的代码做同样的事情
另一方面,我正在寻找一种只渲染视图而不必发布/获取的东西,并生成一个简单的字符串,我可以通过电子邮件代码发送。
不会出现错误的东西,比如两次发布标题或伪造数据
EX:
//code which does not fire Render, RenderPartial... etc
var email = emailFramework.Create(viewData, view);
请参阅下面的“我的解决方案”或点击此链接:
使用spark的我的解决方案:(12/30/2009)尝试使用spark view引擎()。它易于使用,比标准引擎更好,并且不需要伪造上下文 您也可以使用这个答案中的函数,但它需要伪造上下文。这是标准视图引擎的工作方式,对此您无能为力 这是我的扩展类,用于生成要字符串的视图。第一个用于标准视图引擎,第二个用于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();
}
}
公共静态类控制器帮助器
{
///将视图渲染为字符串。
公共静态字符串RenderViewToString(此控制器,
字符串viewName,对象viewData)
{
//获取当前响应
var response=HttpContext.Current.response;
//冲洗
response.Flush();
//查找渲染视图
var视图=ViewEngines.Engines.FindPartialView(controller.ControllerContext,viewName).view;
//创建视图上下文
var viewContext=新的viewContext(controller.ControllerContext,视图,
controller.ViewData、controller.TempData);
//由于RenderView直接进入HttpContext.Current,我们必须过滤并删除视图
var oldFilter=response.Filter;
流过滤器=新内存流();
尝试
{
响应。过滤器=过滤器;
viewContext.View.Render(viewContext,null);
response.Flush();
过滤器。位置=0;
var reader=newstreamreader(过滤器、响应、内容编码);
返回reader.ReadToEnd();
}
最后
{
filter.Dispose();
响应。过滤器=旧过滤器;
}
}
///将视图渲染为字符串。
公共静态字符串RenderSparkToString(此控制器,
字符串viewName,对象viewData)
{
var视图=ViewEngines.Engines.FindPartialView(controller.ControllerContext,viewName).view;
//创建视图上下文
var viewContext=新的viewContext(controller.ControllerContext,视图,
controller.ViewData、controller.TempData);
var sb=新的StringBuilder();
var编写器=新的StringWriter(sb);
viewContext.View.Render(viewContext,writer);
writer.Flush();
使某人返回字符串();
}
}
我为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();
}
不过我同意安德鲁的观点。我希望有一种更简单的方式使用web表单视图引擎来实现这一点。为什么需要从视图创建电子邮件?为什么不使用普通的旧模板文件?我一直都在这样做——我制作一个模板,并使用castle项目中的NVelocity引擎(不要与NVelocity视图引擎混淆)来渲染模板 例如:
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 MVC ViewEngine所做的,但它是Spark中的,只需按照下面最新的链接进行操作 更新(2009年12月30日)清洁版:
(2009年11月16日)或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或混乱路由数据李>
- 它可以实现页眉/页脚来允许模板李>
- 您可以使用循环、条件等
- 它干净,重量轻,特别是如果你打算完全转移到火花查看引擎李>
,如果您需要简单的文本替换,.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
Welcome-{SITE\u NAME}
感谢您在{SITE\u NAME}注册
您的帐户已激活并准备就绪
要登录,请访问并使用以下凭据:
用户名:{username}
密码:使用您注册的密码
-{SITE_NAME}团队
同样,这只适用于简单的字符串替换。如果您计划通过电子邮件发送更多数据,则需要正确格式化数据,然后将其替换。虽然这是一个有点旧的线程,我会鼓励你看看MVCMALNER NuGET包——它大大简化了整个事情,使邮件程序的行为为LI/P>< P>你可以考虑使用MVCMALULUGET——它只做你正在寻找的并且干净的。请参阅NuGet包和
希望有帮助 您好,LukLed,我熟悉Spark View引擎,以前也考虑过这个解决方案,您可能是对的,因为这最终将是最好的方式。最终我可能会被迫走上这条路。然而,我觉得在我的项目中添加第二个视图引擎只会增加