Я пытаюсь использовать пользовательские (производные) RazorViewEngine AND предварительно скомпилированные представления с использованием RazorGenerator.Использование настраиваемых представлений RazorViewEngine AND RazorGenerator
Некоторый контекст:
У нас есть базовый продукт, который мы используем для различных реализаций клиента. При этом у нас есть основной набор базовых представлений. Большинство просмотров работает большую часть времени. Сейчас мы в конечном итоге копируем существующие представления для каждого нового решения и при необходимости модифицируем. Это заканчивается тем, что 95% просмотров совпадают между клиентами и 5% изменены.
Я хочу сделать базовый набор представлений, скомпилировать их в DLL и повторно использовать их через клиентов. Пока что я хорошо работаю, используя RazorGenerator.
Теперь следующим шагом является возможность настройки (переопределения) видов. Однако есть предостережение. Наше приложение имеет два «режима», в которых находится пользователь. В режиме, в котором они находятся, может потребоваться другое представление.
Я создал производный класс из RazorGeneratorView. Это представление в основном проверяет «OrderingMode» из объекта UserProfile, который разрешает Autofac. На основе режима - локатор пути заменяется на разрешение представления.
Идея создания отдельных клиентских приложений будет пытаться разрешить представление сначала в традиционной папке Views. Только я добавляю в подкаталог Views/{OrderingMode}/{Controller}/{View} .cshtml.
Если вид не найден - тогда он будет выглядеть в скомпилированной библиотеке (основные виды).
Это позволяет мне переопределять отдельные виды/частичные части, как это необходимо для клиентов.
public PosViewEngine() : base()
{
//{0} = View Name
//{1} = ControllerName
//{2} = Area Name
AreaViewLocationFormats = new[]
{
//First look in the hosting application area folder/Views/ordering type
//Areas/{AreaName}/{OrderType}/{ControllerName}/{ViewName}.cshtml
"Areas/{2}/Views/%1/{1}/{0}.cshtml",
//Next look in the hosting application area folder/Views/ordering type/Shared
//Areas/{AreaName}/{OrderType}/{ControllerName}/{ViewName}.cshtml
"Areas/{2}/Views/%1/Shared/(0}.cshtml",
//Finally look in the IMS.POS.Web.Views.Core assembly
"Areas/{2}/Views/{1}/{0}.cshtml"
};
//Same format logic
AreaMasterLocationFormats = AreaViewLocationFormats;
AreaPartialViewLocationFormats = new[]
{
//First look in the hosting application area folder/Views/ordering type
//Areas/{AreaName}/{OrderType}/{ControllerName}/Partials/{PartialViewName}.cshtml
"Areas/{2}/Views/%1/{1}/Paritals/{0}.cshtml",
//Next look in the hosting application area folder/Views/ordering type/Shared
//Areas/{AreaName}/{OrderType}/{ControllerName}/{ViewName}.cshtml
"Areas/{2}/Views/%1/Shared/(0}.cshtml",
//Finally look in the IMS.POS.Web.Views.Core
"Areas/{2}/Views/{1}/{0}.cshtml"
};
ViewLocationFormats = new[]
{
"Views/%1/{1}/{0}.cshtml",
"Views/%1/Shared/{0}.cshtml",
"Views/{1}/{0}.cshtml",
"Views/Shared/{0}.cshtml"
};
MasterLocationFormats = ViewLocationFormats;
PartialViewLocationFormats = new[]
{
"Views/%1/{1}/Partials/{0}.cshtml",
"Views/%1/Shared/{0}.cshtml",
"Views/{1}/Partials/{0}.cshtml",
"Views/Shared/{0}.cshtml"
};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
return base.CreatePartialView(controllerContext, partialPath.ReplaceOrderType(CurrentOrderingMode()));
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
OrderType orderType = CurrentOrderingMode();
return base.CreateView(controllerContext, viewPath.ReplaceOrderType(orderType), masterPath.ReplaceOrderType(orderType));
}
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
return base.FileExists(controllerContext, virtualPath.Replace("%1/",string.Empty));
}
private OrderType CurrentOrderingMode()
{
OrderType result;
_profileService = DependencyResolver.Current.GetService<IUserProfileService>();
if (_profileService == null || _profileService.OrderingType == 0)
{
IApplicationSettingService settingService =
DependencyResolver.Current.GetService<IApplicationSettingService>();
result =
settingService.GetApplicationSetting(ApplicationSettings.DefaultOrderingMode)
.ToEnumTypeOf<OrderType>();
}
else
{
result = _profileService.OrderingType;
}
return result;
}
}
Здесь используется класс StartUp, используемый RazorGenerator для регистрации ViewEngine.
public static class RazorGeneratorMvcStart
{
public static void Start()
{
var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly)
{
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
Проблема заключается в том:
- Этот код выполняется в последний раз (после того, как я зарегистрировать PosViewEngine) и вставляет двигатель на первой позиции (это означает, что это двигатель, который получает разрешен 1-го при обслуживании ответы). Это заканчивает поиск взгляда - это основной вид.
Если я изменить код в StartUp зарегистрировать мой пользовательский вид двигателя первый первый, а затем RazorGenerator двигатель
public static void Start() { var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) { UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal }; ViewEngines.Engines.Clear(); ViewEngines.Engines.Insert(0, new PosViewEngine()); ViewEngines.Engines.Insert(1, engine); // StartPage lookups are done by WebPages. VirtualPathFactoryManager.RegisterVirtualPathFactory(engine); }
Я в конечном итоге с исключением на FileExists (ControllerContext controllerContext, строка виртуальный_путь) method - «Относительный виртуальный путь« Views/Account/LogOn.cshtml »здесь не разрешен».
Очевидно, что это связано с тем, что физические и виртуальные пути смешиваются.
Похоже, что кто-то пытался сделать то же самое here, но я не видел ответа на это.
Может ли это использоваться для добавления пользовательского контента в выходящие виды? Я опубликовал это http://stackoverflow.com/questions/38303160/how-to-use-razor-to-process-dynamic-templates-included-in-web-page – Andrus
Не с этим подходом. Это скорее соглашение, в котором я предоставил базовый набор представлений действиям контроллера и при необходимости заменил их. Что бы вы могли для своего вопроса использовать пользовательский базовый вид, чтобы выставлять свои собственные свойства и что-то вроде RazorEngine, чтобы вводить контент через свойство. – JDBennett