Asp.Net MVC 项目预编译 View
最近做项目是遇到一个问题,在我们的view中经常遇到一些匿名类型对象,然后在通过RenderPartial输出这些对象。
还是举个例子吧,有3个view Index.cshtml、Test.cshtml、Test2.cshtml
它们的层次结构如图:
它们的代码如下:
Index.cshtml
[csharp]
@{
Layout = null;
var obj = new[] {
new {name="majiang",age=27},
new {name="luyang",age=26}
};
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<p>
@{
<h2>@(obj.GetType().Assembly.Location)</h2>
Html.RenderPartial("Test", obj);
Html.RenderPartial("Test2", obj);
}
</p>
</body>
</html>
@{
Layout = null;
var obj = new[] {
new {name="majiang",age=27},
new {name="luyang",age=26}
};
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<p>
@{
<h2>@(obj.GetType().Assembly.Location)</h2>
Html.RenderPartial("Test", obj);
Html.RenderPartial("Test2", obj);
}
</p>
</body>
</html>
Test.cshtml 和Test2.cshtml
[csharp] view plaincopyprint?@{
Layout = null;
var obj = this.Model;
var a = new {name="majiang",age=27};
<h2>@(a.GetType().Assembly.Location)</h2>
foreach (var item in obj)
{
<h3>@item.name</h3>
<h3>@item.age</h3>
}
}
@{
Layout = null;
var obj = this.Model;
var a = new {name="majiang",age=27};
<h2>@(a.GetType().Assembly.Location)</h2>
foreach (var item in obj)
{
<h3>@item.name</h3>
<h3>@item.age</h3>
}
}
运行结果Test2.cshtml有错误 提示:
为什么在test里面是对的而到了test2就错了,这2个view只是路径不同,对就是路径不同导致生成dll的路径也不同吗?让我们来证实一下
首先把 test2里面的代码修改为:
@{
Layout = null;
var obj = this.Model;
var a = new { name = "majiang", age = 27 };
<h2>@(a.GetType().Assembly.Location)</h2>
@* foreach (var item in obj)
{
<h3>@item.name</h3>
<h3>@item.age</h3>
}*@
}
运行结果如图:
很明显test和index在同一目录下,它们生成的匿名类型也在同一个dll中,而test2 不再这一目录中那么生成的匿名类型也不再同一dll中。
为什么会这样了,让我们来看看源代码吧
在BuildManagerCompiledView类的 public void Render(ViewContext viewContext, TextWriter writer)方法中有
Type type = BuildManager.GetCompiledType(ViewPath);
而BuildManager的定义是:
internal IBuildManager BuildManager {
get {
if (_buildManager == null) {
_buildManager = new BuildManagerWrapper();
}
return _buildManager;
}
set {
_buildManager = value;
}
}
再让我们看看BuildManagerWrapper类
internal sealed class BuildManagerWrapper : IBuildManager {
bool IBuildManager.FileExists(string virtualPath) {
return BuildManager.GetObjectFactory(virtualPath, false) != null;
}
Type IBuildManager.GetCompiledType(string virtualPath) {
return BuildManager.GetCompiledType(virtualPath);
}
ICollection IBuildManager.GetReferencedAssemblies() {
return BuildManager.GetReferencedAssemblies();
}
Stream IBuildManager.ReadCachedFile(string fileName) {
return BuildManager.ReadCachedFile(fileName);
}
Stream IBuildManager.CreateCachedFile(string fileName) {
return BuildManager.CreateCachedFile(fileName);
}
}
看来view的编译取决于系统的BuildManager,它既是程序集内部类同时也是密封类要扩展它不太现实。
那么这个如何解决了?既然我们不能让所有view动态编译到相同的dll中,那么如果把这几个view预编译能否编译到当前项目dll中了?(维护比较麻烦因为修改view就会更新view所在项目的dll),是否可以解决了?理论是可行的让我们试试吧。
首先让我们安装
Razor Generator
其次.使用NuGet安裝PrecompiledMvcViewEngine。
修改view属性中的自定义工具为RazorGenerator,修改如图
最后我们还原test2,最终运行结果:
最终运行成功。
推荐阅读
-
asp.net core项目mvc权限控制:分配权限
-
在Asp.Net Core MVC 3.0 视图运行时编译
-
ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承
-
ASP.NET MVC项目中App_Code目录在程序应用
-
asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFactory,DALMsSql'.
-
把ASP.NET MVC项目部署到本地IIS上的完整步骤
-
ASP.Net MVC OA项目笔记<四>
-
ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)
-
使用Asp.Net Core MVC 开发项目实践[第一篇:项目结构说明]
-
ASP.Net MVC OA项目笔记<二>