我们有一个基于主题的自定义RazorViewEngine
。
public CustomViewEngine(string theme)
{
PartialViewLocationFormats = new[]
{
"~/Views/PartialViews/" + theme + "/{0}.cshtml",
"~/Views/PartialViews/Base/{0}.cshtml"
}; // This is simplified, we actually have some themes falling back to some other themes before falling back to Base
}
protected void Application_Start()
{
string theme = GetTheme(); // read from config file
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine(theme));
}
当主题为静态时(例如,来自配置文件且从不更改),这一切都好。
但是现在我们需要使主题具有动态(用户可以对其进行更改)。
最好的方法是什么?
如果一次发送一个请求,则可以在页面加载中设置ViewEngine
(在Controller
中,而不是在Application_Start
中),但是我担心它可能会加载错误的主题当人们同时点击页面时。
public class HomeController : Controller
{
public ActionResult Index()
{
string selectedTheme = GetUserTheme(); // eg. HttpContext.Current.Request["theme"]
// Reset ViewEngine every page load because selectedTheme may have changed
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine(selectedTheme));
// Putting Thread.Sleep here (to simulate concurrent requests) and opening multiple
// tabs with different theme selections will make some tabs load the wrong theme :(
return View();
}
}
您如何正确地获得CustomViewEngine
来选择正确的主题并在并发请求中保持强大?
还是有一种方法可以替代 ViewEngine逻辑,以便我们可以编写自己的函数来定位.cshtml文件(而不是仅传递可能的文件位置数组)?
编辑:
显然,解决方案是覆盖FileExists
,尽管它会使页面加载速度变慢。
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
// Do your own logic here, look up Request and return true or false
return base.FileExists(controllerContext, virtualPath);
}
http://robhead89.blogspot.com/2014/01/aspnet-viewengine-caching-and-how-to.html