在 mvc 中使用 IViewLocationExpander
Working with IViewLocationExpander in mvc
我想从自定义位置呈现视图,为此我实现了
IViewLocationExpander
接口中的一个 class。我在Startup
class中注册了相同的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;
}
}
我想从自定义位置呈现视图,为此我实现了
IViewLocationExpander
接口中的一个 class。我在Startup
class中注册了相同的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;
}
}