我的大多数视图都是普通<action>.cshtml
文件夹层次结构中的常规/Views/<Controller>
文件。这些是git中的源代码控制,并以通常的“rip and replace”方式部署。
但是我也使用Razor渲染模板来创建HTML电子邮件,电子邮件.cshtml模板特定于每个客户端。因此,我希望能够从外部 Application Root文件夹加载和呈现它们,因此在部署期间不会丢失特定于客户端的自定义。
我已经成功创建并注册了IViewLocationExpander
接口的实现,这适用于Application Root中的文件夹:
public class EmailViewLocationExpander : IViewLocationExpander
{
protected readonly String _TemplateFolder;
public EmailViewLocationExpander( String TemplateFolder )
{
_TemplateFolder = TemplateFolder.Trim('/');
}
public void PopulateValues( ViewLocationExpanderContext context )
{
}
public IEnumerable<string> ExpandViewLocations( ViewLocationExpanderContext context, IEnumerable<string> viewLocations )
{
var result = new List<String>( viewLocations );
result.Add( $"/{ _TemplateFolder }/Email/{{0}}.cshtml" );
result.Add( $"/{ _TemplateFolder }/Shared/{{0}}.cshtml" );
return result;
}
}
它似乎不适用于Application Root相对之外的路径,例如, /../Templates
似乎不起作用。
我目前还依赖于为我的电子邮件模板设置自定义_ViewStart.cshtml
,并且阅读Mvc source code让我认为我唯一的选择是实施自定义IFileProvider
来引用当前应用程序根目录之外的物理文件系统 - 是正确的,任何人都可以帮我一个例子吗?
答案 0 :(得分:1)
这对我来说似乎是对的。 ViewLocationExpander
处理相对于wwwroot文件夹的路径,因此它对于指定文件之外的文件的路径不会有用。
这是一篇关于实施IFileProvider
的非常好的文章。这些文章演示了创建和IFileProvider
访问存储在数据库中的视图,但从文件系统中读取它们将更加容易。因此,它是一个很好的考虑因素。 https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location
我注意到的一点是,IFileProvider
的工作方式非常酷。您将自定义实现注册为RazorViewEngine的选项,如下所示,当ViewEngine需要获取文件时,它会按顺序询问每个FileProvider,直到返回它为止。
public void ConfigureServices(IServiceCollection services)
{
string customLocation = @"c:\mylocation\"
// Add framework services.
services.AddMvc();
services.Configure<RazorViewEngineOptions>(opts =>
opts.FileProviders.Add(
new MyCustomFileProvider(customLocation)
)
);
}
所以最后,你基本上只是实现了FileProvider
来为某些特定的url端点提供文件。你可以从任何你喜欢的地方获得它们。