在 mvc 中使用 IViewLocationExpander

Working with IViewLocationExpander in mvc

我想从自定义位置呈现视图,为此我实现了 IViewLocationExpander 接口中的一个 class。我在Startupclass中注册了相同的class如下

Startup Class

public void ConfigureServices(IServiceCollection services)
{
    … 
    //Render view from custom location.
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new CustomViewLocationExpander());
    });
    … 
}

CustomViewLocationExpander Class

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {

        var session = context.ActionContext.HttpContext.RequestServices.GetRequiredService<SessionServices>();
        string folderName = session.GetSession<string>("ApplicationType");

        viewLocations = viewLocations.Select(f => f.Replace("/Views/", "/" + folderName + "/"));


        return viewLocations;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {

    }
}

最后,我的应用程序的视图组织如下:

我的问题:如果我从以下 URL:

ViewsFrontend 文件夹访问 Views/Login 视图
http://localhost:56739/trainee/Login/myclientname 

然后马上把浏览器里的URL改成:

http://localhost:56739/admin/Login/myclientname

在这种情况下,它仍然引用 ViewsFrontend 文件夹,尽管它 应该 现在引用 ViewsBackend 文件夹,因为 URL 以 trainee 开头的应指代 ViewsFrontend 文件夹,而以 admin 开头的应指代 ViewsBackend 文件夹。

另外,在浏览器中更改URL后,只调用了PopulateValues()方法,没有调用ExpandViewLocations()方法

如何重新配置​​此 class 以用于其他文件夹?

PopulateValues 作为一种指定参数的方式存在,您的视图查找将根据每个请求而变化。由于您没有填充它,视图引擎使用来自早期请求的缓存值

要解决这个问题,请将您的 ApplicationType 变量添加到 PopulateValues() 方法中,并且只要该值发生变化,就会调用 ExpandValues() 方法:

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        string folderName = context.Values["ApplicationType"];
        viewLocations = viewLocations.Select(f => f.Replace("/Views/", "/" + folderName + "/"));

        return viewLocations;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        var session = context.ActionContext.HttpContext.RequestServices.GetRequiredService<SessionServices>();
        string applicationType = session.GetSession<string>("ApplicationType");
        context.Values["ApplicationType"] = applicationType;
    }
}