Прерывистая проблема пути просмотра с пользовательским механизмом просмотра бритвы MVC
У нас есть приложение Sass, в котором мы только что реализовали пользовательский механизм просмотра бритвы, чтобы позволить нам обслуживать различные виды в зависимости от текущего пользователя, который вошел в систему. В Dev это все работало нормально. Однако в Production (общий веб-хостинг) у нас периодически возникают проблемы с попыткой обслужить несуществующее представление, используя неправильный путь представления.
Что происходит, так это то, что после развертывания все работает нормально. Затем примерно через 20 - 30 минут мы начинаем получать просмотр не найденных ошибок. Если я изменю файл web.conf для принудительного перезапуска пула приложений, то все снова будет работать нормально... какое-то время.
Похоже, что в некоторых случаях метод FileExists возвращает истину для этих путей. Не уверен, что это связано с проблемой кэширования или с общим хостом, веб-фермой, несколькими запросами на одну и ту же страницу в одно и то же время, когда результаты 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;
}
}
1 ответ
Оказывается, что в режиме релиза используется кэширование, которое вызывает проблемы, которые у меня были. Вам также необходимо переопределить методы FindView и FindPartialView и установить для useCache значение false:
//to not used Cached paths. see one of the comments here: http://lonetechie.com/2012/09/25/multi-tenant-architecture-with-asp-net-mvc-4/
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
return base.FindView(controllerContext, viewName, masterName, false);
}
//to not used Cached paths. see one of the comments here: http://lonetechie.com/2012/09/25/multi-tenant-architecture-with-asp-net-mvc-4/
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
return base.FindPartialView(controllerContext, partialViewName, false);
}