RazorGenerator PrecompiledMvc​​Engine无法跨程序集找到部分视图或编辑器模板

时间:2013-07-23 17:05:47

标签: c# asp.net-mvc-4 razor razorgenerator

我有一个大的MVC 4站点,每个MVC区域分成一个项目。我们使用RazorGenerator将所有视图预编译到项目程序集中进行部署,并使用PrecompiledMvcEngine作为ViewEngine

我刚创建了一个新的区域,我希望与其他程序集共享Shared个视图,但在尝试查找部分视图时没有显示InvalidOperationException,而且没有显示任何DisplayTemplates或EditorTemplates似乎也找到了。

我认为它类似于this question中描述的问题。

我在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")一样的部分引用时,我得到了异常。看来Razor正在寻找正确的路径

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的源代码,看来它只查找程序集中的视图。

我最初认为视图系统会在尝试解析路径时查看所有已注册的ViewEngine,但这似乎是一个不正确的假设(我可以看到为什么不会这样做)。

有没有办法在多个程序集之间共享视图?

更新

我通过创建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);
    }
}

这种方法有更好的替代方案或陷阱吗?

0 个答案:

没有答案