我想从自定义位置呈现视图,为此我在一个类中实现了 IViewLocationExpander
接口。 我在 Startup
类中注册了相同的类,如下所示。
Startup 类
public void ConfigureServices(IServiceCollection services)
{
…
//Render view from custom location.
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new CustomViewLocationExpander());
});
…
}
CustomViewLocationExpander 类
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
文件夹,因为以 trainee
开头的 URL 应该引用 ViewsFrontend
文件夹,而以 admin
开头的 URL 应该引用 ViewsBackend
文件夹。
此外,在浏览器中更改 URL 后,它只调用 PopulateValues()
方法,而不调用 ExpandViewLocations()
方法。
我怎样才能重新配置这个类来为这个其他文件夹工作?
答案
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;
}
}