in ASP.NET Core MVC, is it possible to add a View folder from outside the project folder?

徘徊边缘 提交于 2019-12-12 19:24:29

问题


The majority of my views are regular <action>.cshtml files in the normal /Views/<Controller> folder hierarchy. These are source controlled in git and deployed in the usual "rip and replace" way.

However I also use Razor for rendering templates to create HTML emails, and the email .cshtml templates are specific to each client. I therefore want to be able to load and render them from outside the Application Root folder, so the client-specific customisations are not lost during deployment.

I have successfully created and registered an implementation of the IViewLocationExpander interface and this works for folders inside the 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;
    }
}

It does not seem to work for paths other than Application Root relative, so e.g. /../Templates doesn't seem to work.

I also currently rely on having a custom _ViewStart.cshtml for my email templates, and reading the Mvc source code leads me to think that my only option is to implement a custom IFileProvider to reference the physical file system outside the current Application Root - is that right and can anyone help me with an example if it is?


回答1:


That seems right to me. The ViewLocationExpander deals with paths relative to the wwwroot folder so it's not going to be useful for specify paths to files outside of that.

Here is a pretty good article on implementing an IFileProvider. The articles demonstrates creating and IFileProvider for accessing views stored in a database but reading them from the file system will be even easier. So it's a great outline of what to consider. https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location

One thing I noted is that the way the way the IFileProvider works is pretty cool. You register your custom implementation as an option to the RazorViewEngine like below and when the ViewEngine needs to get a file, it asks each FileProvider, in order, for that file until one returns it.

 public void ConfigureServices(IServiceCollection services)
 {
    string customLocation = @"c:\mylocation\"

    // Add framework services.
    services.AddMvc();
    services.Configure<RazorViewEngineOptions>(opts => 
        opts.FileProviders.Add(
            new MyCustomFileProvider(customLocation)
        )
    );
 }

So in the end, you basically just implement your FileProvider to provide files for some specific url endpoints. You can obtain them from anyplace you like.



来源:https://stackoverflow.com/questions/42298745/in-asp-net-core-mvc-is-it-possible-to-add-a-view-folder-from-outside-the-projec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!