我正在使用Postal呈现MVC Razor视图并通过电子邮件发送它们。我有一个我专门为电子邮件视图定义的自定义CSS。目前我将它们包括在内:
@Styles.Render("~/Content/EmailStyles.css")
但是,这只包括样式表的相对链接,这在电子邮件中不起作用:
<link href="/Content/EmailStyles.css" rel="stylesheet"/>
我希望将样式表内联,以便它在电子邮件中正常运行。在MVC视图中呈现基于文件的资源的内容的最佳方法是什么?
答案 0 :(得分:33)
我自己也有同样的问题,遇到Premailer.Net。它看起来像你需要的库。这是你必须做的:
创建一个扩展方法,以帮助您将CSS嵌入到您的页面中;有an answer on a question on how to embed HTML in a Razor view可以帮助你。我修改了它 嵌入CSS:
public static class HtmlHelpers
{
public static MvcHtmlString EmbedCss(this HtmlHelper htmlHelper, string path)
{
// take a path that starts with "~" and map it to the filesystem.
var cssFilePath = HttpContext.Current.Server.MapPath(path);
// load the contents of that file
try
{
var cssText = System.IO.File.ReadAllText(cssFilePath);
var styleElement = new TagBuilder("style");
styleElement.InnerHtml = cssText;
return MvcHtmlString.Create(styleElement.ToString());
}
catch (Exception ex)
{
// return nothing if we can't read the file for any reason
return null;
}
}
}
然后在您的Razor模板中,转到:
@Html.EmbedCss("~/Content/EmailStyles.css")
嵌入CSS文字。
在项目中安装Premailer.Net软件包;你可以通过NuGet获得它。
将您的Razor视图渲染成一个字符串(我想这就是您在过程中使用的邮件?我相信RazorEngine也可以这样做。)
通过Premailer.Net运行字符串:
PreMailer pm = new PreMailer();
string premailedOutput = pm.MoveCssInline(htmlSource, false);
以电子邮件方式发送!
我现在已经在生产中使用这种技术了一段时间,它看起来效果很好。
编辑:请记住,伪元素上的样式无法内联,因为它们在标记中不存在。我也注意到Premailer.Net中的奇怪小错误 - 我认为它们的特异性和级联规则并不完全一致。尽管如此,它还是非常好的,而且还有一段我不必编写的代码!
答案 1 :(得分:9)
赞成Paul的回答,但是我发现他的帮助方法的这个版本对我来说工作得更好(不会尝试编写CSS中的引号之类的东西):< / p>
public static class CssHelper
{
public static IHtmlString EmbedCss(this HtmlHelper htmlHelper, string path)
{
// take a path that starts with "~" and map it to the filesystem.
var cssFilePath = HttpContext.Current.Server.MapPath(path);
// load the contents of that file
try
{
var cssText = File.ReadAllText(cssFilePath);
return htmlHelper.Raw("<style>\n" + cssText + "\n</style>");
}
catch
{
// return nothing if we can't read the file for any reason
return null;
}
}
}
答案 2 :(得分:0)
我想你需要有一个自定义助手。在我的头顶上,没有这样的方法来呈现css路径,包括网站的绝对路径。
e.g。 HTTP:www.example.com/css/EmailStyles.css
答案 3 :(得分:0)
我意识到这是一个老问题,但这里是 dprothero 答案的修改版本,它将嵌入捆绑包。 创建一个静态 C# 类并将此方法放入其中:
public static IHtmlString EmbedCss(this HtmlHelper htmlHelper, string path)
{
try
{
// Get files from bundle
StyleBundle b = (StyleBundle)BundleTable.Bundles.GetBundleFor("~/Content/css");
BundleContext bc = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, "~/Content/css");
List<BundleFile> files = b.EnumerateFiles(bc).ToList();
// Create string to return
string stylestring = "";
// Iterate files in bundle
foreach(BundleFile file in files)
{
// Get full path to file
string filepath = HttpContext.Current.Server.MapPath(file.IncludedVirtualPath);
// Read file text and append to style string
string filetext = File.ReadAllText(filepath);
stylestring += $"<!-- Style for {file.IncludedVirtualPath} -->\n<style>\n{filetext}\n</style>\n";
}
return htmlHelper.Raw(stylestring);
}
catch
{
// return nothing if we can't read the file for any reason
return null;
}
然后转到您想在其中使用它的任何视图。确保添加 using 语句,以便您的视图可以看到 CSS 助手。我还使用 TempData 来决定是否内联呈现它:
<!-- Using statement -->
@using Namespace.Helpers;
<!-- Check tempdata flag for whether or not to render inline -->
@if (TempData["inlinecss"] != null)
{
<!-- Embed CSS with custom code -->
@Html.EmbedCss("~/Content/css")
}
else
{
<!-- Use links to reference CSS -->
@Styles.Render("~/Content/css")
}