【发布时间】:2015-04-03 16:07:07
【问题描述】:
我们有一个 Sass 应用程序,我们刚刚实现了一个自定义 razor 视图引擎,以允许我们根据当前登录的用户提供不同的视图。在 Dev 中,这一切都很好。但是,在生产环境(共享网络主机)中,我们会遇到间歇性问题,即尝试使用不正确的视图路径提供不存在的视图。
发生的情况是,在我们部署之后,它工作正常。然后大约 20 - 30 分钟后,我们开始收到未找到视图的错误。如果我更改 web.conf 文件以强制重新启动应用程序池,那么一切都会再次正常运行......一段时间。
似乎不知何故,FileExists 方法在某些情况下以某种方式为这些路径返回 true。不确定这是由于缓存问题,还是在共享主机、网络农场、同一页面的多个请求同时从 FileExists 交叉获取结果等?我不知道。
错误:
System.Web.HttpException: The file '/Areas/OrderMgmt/Views/HH/ManageOrders/Pickup.cshtml' does not exist.
在上述情况下,该视图不存在,它位于 _Base 文件夹中:/Areas/OrderMgmt/Views/HH/ManageOrders/Pickup.cshtml
下面是自定义视图引擎代码:
{
//http://lonetechie.com/2012/09/25/multi-tenant-architecture-with-asp-net-mvc-4/
public class MulitTenantRazorViewEngine : RazorViewEngine
{
public const string baseFolderPath = "_Base";
public MulitTenantRazorViewEngine()
{
_logger = LogManager.GetLogger(GetType());
AreaViewLocationFormats = new[] {
"~/Areas/{2}/Views/%1/{1}/{0}.cshtml",
"~/Areas/{2}/Views/%1/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/%1/Shared/{0}.cshtml",
"~/Areas/{2}/Views/%1/Shared/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.cshtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.cshtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.vbhtml"
};
AreaMasterLocationFormats = new[] {
"~/Areas/{2}/Views/%1/{1}/{0}.cshtml",
"~/Areas/{2}/Views/%1/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/%1/Shared/{0}.cshtml",
"~/Areas/{2}/Views/%1/Shared/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.cshtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.cshtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.vbhtml"
};
AreaPartialViewLocationFormats = new[] {
"~/Areas/{2}/Views/%1/{1}/{0}.cshtml",
"~/Areas/{2}/Views/%1/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/%1/Shared/{0}.cshtml",
"~/Areas/{2}/Views/%1/Shared/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.cshtml",
"~/Areas/{2}/Views/_Base/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.cshtml",
"~/Areas/{2}/Views/_Base/Shared/{0}.vbhtml"
};
ViewLocationFormats = new[] {
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/{1}/{0}.vbhtml",
"~/Views/%1/Shared/{0}.cshtml",
"~/Views/%1/Shared/{0}.vbhtml",
"~/Views/_Base/{1}/{0}.cshtml",
"~/Views/_Base/{1}/{0}.vbhtml",
"~/Views/_Base/Shared/{0}.cshtml",
"~/Views/_Base/Shared/{0}.vbhtml"
};
MasterLocationFormats = new[] {
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/{1}/{0}.vbhtml",
"~/Views/%1/Shared/{0}.cshtml",
"~/Views/%1/Shared/{0}.vbhtml",
"~/Views/_Base/{1}/{0}.cshtml",
"~/Views/_Base/{1}/{0}.vbhtml",
"~/Views/_Base/Shared/{0}.cshtml",
"~/Views/_Base/Shared/{0}.vbhtml"
};
PartialViewLocationFormats = new[] {
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/{1}/{0}.vbhtml",
"~/Views/%1/Shared/{0}.cshtml",
"~/Views/%1/Shared/{0}.vbhtml",
"~/Views/_Base/{1}/{0}.cshtml",
"~/Views/_Base/{1}/{0}.vbhtml",
"~/Views/_Base/Shared/{0}.cshtml",
"~/Views/_Base/Shared/{0}.vbhtml"
};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
var PassedController = controllerContext.Controller as BaseController;
Debug.Assert(PassedController != null, "PassedController != null");
return base.CreatePartialView(controllerContext, GetTenantViewPath(partialPath, PassedController));
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var PassedController = controllerContext.Controller as BaseController;
Debug.Assert(PassedController != null, "PassedController != null");
return base.CreateView(controllerContext, GetTenantViewPath(viewPath, PassedController), GetTenantViewPath(masterPath, PassedController));
}
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
var PassedController = controllerContext.Controller as BaseController;
Debug.Assert(PassedController != null, "PassedController != null");
var tenantViewPath = GetTenantViewPath(virtualPath, PassedController);
var isFound = base.FileExists(controllerContext, tenantViewPath);
_logger.Debug(String.Format("Is Found: {0} Path: {1}.", isFound.ToString(), tenantViewPath));
return isFound;
}
private string GetTenantViewPath(string virtualPath, BaseController PassedController)
{
string strReplacementString = "";
if (PassedController == null)
{
strReplacementString = baseFolderPath;
}
else if(PassedController.User == null) {
strReplacementString = baseFolderPath;
}
else
{
strReplacementString = PassedController.User.CurrentAccountCode ?? baseFolderPath;
}
return virtualPath.Replace("%1", strReplacementString);
}
private readonly ILog _logger;
}
}
【问题讨论】:
-
我建议你改写你的问题并选择更好的标签。自定义视图引擎与 .NET 路由无关。
标签: asp.net-mvc razor asp.net-mvc-5 viewengine