Asp.Net MVC 项目预编译 View

最近做项目是遇到一个问题,在我们的view中经常遇到一些匿名类型对象,然后在通过RenderPartial输出这些对象。

还是举个例子吧,有3个view Index.cshtml、Test.cshtml、Test2.cshtml

它们的层次结构如图:

它们的代码如下:

Index.cshtml

 Test.cshtml 和Test2.cshtml

 运行结果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,最终运行结果:

最终运行成功。在这里最好的解决方案还是用强类型,此文章只是从技术的角度来分析问题解决问题,仅供大家参考。欢迎大家拍砖!

posted on   dz45693  阅读(4258)  评论(5编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2012年11月 >
28 29 30 31 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示