Asp.Net MVC 項目預編譯 View


最近做項目是遇到一個問題,在我們的view中經常遇到一些匿名類型對象,然后在通過RenderPartial輸出這些對象。

還是舉個例子吧,有3個view Index.cshtml、Test.cshtml、Test2.cshtml

它們的層次結構如圖:

它們的代碼如下:

Index.cshtml

@{
    Layout = null;
    var obj = new[] {
    new {name="majiang",age=27},
    new {name="luyang",age=26}
    };
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @{
               <h2>@(obj.GetType().Assembly.Location)</h2>
            Html.RenderPartial("Test", obj);
            Html.RenderPartial("Test2", obj);
          }
    </div>
</body>
</html>

 Test.cshtml 和Test2.cshtml

@{
    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,最終運行結果:

最終運行成功。在這里最好的解決方案還是用強類型,此文章只是從技術的角度來分析問題解決問題,僅供大家參考。歡迎大家拍磚!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM