RazorGenerator PrecompiledMvcEngine не может найти частичное представление или шаблоны редактора в сборках
У меня есть большой сайт MVC 4, который разбит на один проект на область MVC. Мы используем RazorGenerator для предварительной компиляции всех наших представлений в сборку проекта для развертывания и использования PrecompiledMvcEngine
за наших ViewEngine
,
Я только что создал новую область, которой я хотел бы поделиться Shared
просмотров из другой сборки, но я получаю InvalidOperationException
при попытке найти частичное представление ни один из DisplayTemplates или EditorTemplates, кажется, не будет найден либо.
Я считаю, что это похоже на проблему, описанную в этом вопросе.
Мой код в RazorGenerator App_Start выглядит так:
var assemblies = new List<Tuple<string, Assembly>>()
{
Tuple.Create("Areas/Area1", typeof(ABC.Project1.AreaRegistration).Assembly),
Tuple.Create("Areas/Area2", typeof(ABC.Project2.AreaRegistration).Assembly),
};
// Get rid of the default view engine
ViewEngines.Engines.Clear();
foreach ( var assembly in assemblies )
{
var engine = new PrecompiledMvcEngine(assembly.Item2, assembly.Item1) {
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
// Allow sharing of Area1 Shares views with Area2
if (assembly.Item1 == "Areas/Area2")
{
var sharedPaths = new[] { "~/Areas/Area1/Views/Shared/{0}.cshtml" };
engine.ViewLocationFormats = engine.ViewLocationFormats.Concat(sharedPaths).ToArray();
engine.MasterLocationFormats = engine.MasterLocationFormats.Concat(sharedPaths).ToArray();
engine.PartialViewLocationFormats = engine.PartialViewLocationFormats.Concat(sharedPaths).ToArray();
}
ViewEngines.Engines.Insert(0, engine);
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
Когда я сталкиваюсь с частичной ссылкой в представлении в Area2, как @Html.Partial("Partials/Footer")
Я получаю исключение. Похоже, что бритва ищет правильный путь
System.InvalidOperationException: The partial view 'Partials/Footer' was not found or no view engine supports the searched locations. The following locations were searched:
~/Areas/Area2/Views/Home/Partials/Footer.cshtml
~/Areas/Area2/Views/Shared/Partials/Footer.cshtml
~/Views/Home/Partials/Footer.cshtml
~/Views/Shared/Partials/Footer.cshtml
~/Areas/Area1/Views/Shared/Partials/Footer.cshtml
at System.Web.Mvc.HtmlHelper.FindPartialView(ViewContext viewContext, String partialViewName, ViewEngineCollection viewEngineCollection)
Глядя на исходный код PrecompiledMvcEngine
Похоже, что он ищет только виды внутри сборки.
Сначала я думал, что система представлений будет просматривать все зарегистрированные ViewEngines при попытке определить путь, но это неверное предположение (и я понимаю, почему этого не делать).
Есть ли способ поделиться мнениями между несколькими сборками?
Обновить
Я работал над этой проблемой, создав собственную версию PrecompiledMvcEngine
это берет список сборок в своем конструкторе. Основное изменение заключается в следующем:
_mappings = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
foreach (var kvp in assemblies)
{
var baseVirtualPath = NormalizeBaseVirtualPath(kvp.Key);
var assembly = kvp.Value;
var mapping = from type in assembly.GetTypes()
where typeof(WebPageRenderingBase).IsAssignableFrom(type)
let pageVirtualPath = type.GetCustomAttributes(inherit: false).OfType<PageVirtualPathAttribute>().FirstOrDefault()
where pageVirtualPath != null
select new KeyValuePair<string, Type>(CombineVirtualPaths(baseVirtualPath, pageVirtualPath.VirtualPath), type);
foreach (var map in mapping)
{
_mappings.Add(map);
}
}
Есть ли лучшая альтернатива или подводные камни с этим подходом?