首页 > 解决方案 > 动态自定义 RazorViewEngine?

问题描述

我们有一个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

标签: asp.netasp.net-mvcrazor

解决方案


推荐阅读