我们有一个ASP.NET MVC应用程序4在它周围3000景色。 我们已经决定将这套意见分成分离的DLL和与RazorGenerator编译。 我们只保留主_Layout.cshtml并在主MVC项目相关文件。
我们无法加载DLL从局部视图,在主MVC项目主视图在一起。 详细描述如下。
什么是已经完成:
意见成功编译成DLL文件(我已经证实,他们是二进制)
在创建对象PrecompiledMvcEngine和用于容纳在Global.asax.cs中使用以下代码中的Application_Start视图每个DLL注册:
。
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
// ...
// some code determining whether we've got an assembly with views
// ...
var engine = new PrecompiledMvcEngine(assembly);
engine.UsePhysicalViewsIfNewer = true;
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
什么不工作:
我无法加载在主MVC项目(比如说_Layout.cshtml)与所述库中的一项所定义的局部视图定义的视图(说Partial.cshtml)。 我用下面的代码在控制器的行动告诉了MVC框架,查看我要求:
var view = "~/Views/" + partialName + ".cshtml";
return View(view, "~/Views/Shared/_Layout.cshtml", model);
该错误消息说:视图“〜/查看/ Partial.cshtml”或它的主人没有被发现或没有视图引擎支持搜索到的位置。 以下位置进行检索:〜/查看/ Partial.cshtml〜/查看/共享/ _Layout.cshtml
当我尝试通过指定单独地加载的观点:
return View("~/Views/Shared/_Layout.cshtml", model);
要么
return View(view, model);
,右视图中找到。 不过,我需要他们一起装载。 代码工作时,我都需要在主MVC项目.cshtml文件。
需要注意的是在编译的DLL的看法有PageVirtualPathAttribute与在控制器的动作,例如指定相同的路径:
namespace SomeBaseNamespace.Views
{
[GeneratedCode("RazorGenerator", "1.5.0.0"), PageVirtualPath("~/Views/Partial.cshtml")]
public class Partial : WebViewPage<PartialModel>
{
[CompilerGenerated]
private static class <Execute>o__SiteContainer3
{
// logic
}
public override void Execute()
{
// logic
}
}
}
综上所述,问题是如何调用存储在主MVC项目与另一个项目中定义的部分编译视图主视图?
在应用程序启动,当你的应用程序调用该行...
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
包含您的外部视图的组件可能已经尚未加载,并且因此不包括作为视图引擎。 其实我建议不要使用AppDomain.CurrentDomain.GetAssemblies()
反正,因为这将包括在启动时加载的所有程序集。
该解决方案是将补充RazorGenerator.Mvc NuGet包到包含编译视图中的每个项目。 这会以类似的方式添加下面的应用程序启动代码,你的...
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(SomeBaseNamespace.Views.RazorGeneratorMvcStart), "Start")]
namespace SomeBaseNamespace.Views
{
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);
}
}
}
注意如何创建使用当前组件的视图引擎(你的意见汇编),并将其添加到静态ViewEngines
集合(包含在主MVC项目中)。
一旦投入生产,我也建议关闭UsePhysicalViewsIfNewer
设置,增加了一个显著的性能开销。
术语
BaseMvc - 剃刀生成的视图,控制器等
ConsumerMvc - 已为此项目和引用布局BaseMvc
摘要
在创建基本控制器视图的递送。 该视图使用一个布局,其存在于经由_ViewStart.cshtml在BaseMvc的ConsumerMvc。 对于我的情况我有项目,不同的布局,因此“指针”布局视图。 我认为这是个有用的例子。
BaseMvc例
我创建了一个AREA
,所以我可以设置默认布局。
/Areas/Components/Controllers/ShoppingController.cs
public ActionResult Basket()
{
return View();
}
/Areas/Components/Views/Shopping/Basket.cshtml
Welcome to the Basket!
/Areas/Components/Views/_ViewStart.cshtml
@{
//-- NOTE: "Layout_Component.cshtml" do not exist in the BaseMVC project. I did not
// experiment with having it in both projects. A tip if you do is to ensure both
// the base and consumer _Layout_Component.cshtml files are both razor
// generated to allow the razor generator to handle the overrride. See
// my other SO answer linked below.
Layout = "~/Views/Shared/_Layout_Component.cshtml";
}
在代码注释的参考链接: 重写鉴于ASP.NET MVC的网站无法正常工作
ConsumerMvc例
/Views/Shared/_Layout_Component.cshtml
@{
Layout = "~/Views/Shared/_Layout_ConsumerMvc.cshtml";
}
@RenderBody()
我的网址
http://www.consumermvc.example.com/Components/Shopping/Basket
并非在所有组件加载Application_Start
被调用。 添加一个额外的处理程序:
AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
{
// ...
// some code determining whether we've got an assembly with views
// ...
var engine = new PrecompiledMvcEngine(args.LoadedAssembly);
engine.UsePhysicalViewsIfNewer = true;
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
文章来源: Razor Generator: how to use view compiled in a library as the partial view for master defined in main mvc project