我们有一个ASP.NET MVC 4应用程序,其中包含大约3000个视图。我们决定将这组视图拆分为单独的DLL,并使用RazorGenerator进行编译。我们只在主MVC项目中保留主_Layout.cshtml和相关文件。
我们无法在主MVC项目中将DLL的部分视图与主视图一起加载。详细说明如下。
已完成的工作:
视图成功编译成DLL(我已经确认它们是二进制文件)
使用Global.asax.cs中Application_Start中的以下代码为包含视图的每个DLL创建并注册PrecompiledMvcEngine对象:
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);
错误消息说: 未找到视图'〜/ Views / 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项目中的主视图?
答案 0 :(得分:1)
在应用开始时,当您的应用调用此行时...
04:05:14Z
包含外部视图的程序集可能尚未加载,因此不包含在视图引擎中。我实际上建议不要使用 List<int> listOfCountries = new List<int> { 1,2,3 };
var query = (
from country in context.Countries.AsNoTracking()
join car in context.Cars.AsNoTracking() on new { CountryID = country.ID}
equals new { CountryID = cars .CountryID }
where listOfCountries.Contains(prv.CountryID)
select car);
,因为这将包括启动时加载的所有程序集。
解决方案是将RazorGenerator.Mvc NuGet包添加到包含已编译视图的每个项目中。这将以与您类似的方式添加以下应用启动代码...
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
请注意这是如何使用当前程序集(您的视图程序集)创建视图引擎,并将其添加到静态AppDomain.CurrentDomain.GetAssemblies()
集合(包含在主MVC项目中)。
一旦投入生产,我还建议关闭[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);
}
}
}
设置,这会增加显着的性能开销。
答案 1 :(得分:0)
调用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);
}
答案 2 :(得分:0)
术语
BaseMvc - 使用Razor生成的视图,控制器等 ConsumerMvc - 具有此项目的布局并引用BaseMvc
摘要的
在基本控制器中创建视图的传递。该视图使用通过BaseMvc中的_ViewStart.cshtml存在于ConsumerMvc中的布局。对于我的情况,我有不同布局的项目,因此&#34;指针&#34;布局视图。我认为这是一个有用的例子。
我创建了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";
}
代码评论中引用的链接:Override view in ASP.NET MVC site not working
<强> /Views/Shared/_Layout_Component.cshtml 强>
@{
Layout = "~/Views/Shared/_Layout_ConsumerMvc.cshtml";
}
@RenderBody()
http://www.consumermvc.example.com/Components/Shopping/Basket