簡體   English   中英

在IIS預熱步驟中預加載ASP.NET MVC視圖

[英]Preload ASP.NET MVC views in IIS warmup step

我最近開始利用IIS通過使用IProcessHostPreloadClient接口向我的Web應用程序應用預熱步驟的能力(請查看此處獲取有關如何設置它的指導)。 這很好,或者至少我認為它確實如此,因為我所做的一個“聰明”的事情是嘗試通過迭代我的控制器並渲染它們來預加載我的視圖。

經過一些試驗和錯誤,我得到了它的工作,一切都很順利。 也就是說,直到我注意到我的系統的所有驗證都不再有效,無論是客戶端還是服務器驗證。 我假設當MVC第一次檢索視圖時,驗證通常會連接到視圖,但我沒有這樣做。 有沒有人知道如何將其包含在我的解決方案中或者以其他方式完成?

代碼:

public class Warmup : IProcessHostPreloadClient
{
    public void Preload(string[] parameters)
    {
        //Pre-render all views
        AutoPrimeViewCache("QASW.Web.Mvc.Controllers", @"Views\");
        AutoPrimeViewCache("QASW.Web.Mvc.Areas.Api.Controllers", @"Areas\Api\Views\", "Api");
    }

    private void AutoPrimeViewCache(string controllerNamespace, string relativeViewPath, string area = null)
    {
        var controllerTypes = typeof(Warmup).Assembly.GetTypes().Where(t => t.Namespace == controllerNamespace && (t == typeof(Controller) || t.IsSubclassOf(typeof(Controller))));
        var controllers = controllerTypes.Select(t => new { Instance = (Controller)Activator.CreateInstance(t), Name = t.Name.Remove("Controller") });

        foreach (var controller in controllers)
        {
            var viewPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, relativeViewPath + controller.Name);
            var viewDir = new DirectoryInfo(viewPath);
            if (viewDir.Exists)
            {
                var viewNames = viewDir.EnumerateFiles("*.cshtml").Select(f => f.Name.Remove(".cshtml")).ToArray();
                PreloadController(controller.Instance, area, viewNames);
            }
        }
    }

    private void PreloadController(Controller controller, string area, params string[] views)
    {
        var viewEngine = new RazorViewEngine();

        var controllerName = controller.GetType().Name.Remove("Controller");
        var http = new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://a.b.com", null), new HttpResponse(TextWriter.Null)));
        var routeDescription = area == null ? "{controller}/{action}/{id}" : area + "/{controller}/{action}/{id}";
        var route = new RouteCollection().MapRoute(
            "Default", // Route name
            routeDescription, // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        var routeData = new RouteData(route, route.RouteHandler);
        routeData.Values.Add("controller", controllerName);
        if (area != null)
        {
            routeData.Values.Add("area", area);
            routeData.DataTokens.Add("area", area);
        }
        routeData.DataTokens.Add("controller", controllerName);
        routeData.Values.Add("id", 1);
        routeData.DataTokens.Add("id", 1);
        var controllerContext = new ControllerContext(http, routeData, controller);
        var vDic = new ViewDataDictionary();
        var vTemp = new TempDataDictionary();

        foreach (var view in views)
        {
            var viewResult = viewEngine.FindView(controllerContext, view, null, false);
            if (viewResult.View == null)
                throw new ArgumentException("View not found: {0} (Controller: {1})".Args(view, controllerName));
            var viewContext = new ViewContext(controllerContext, viewResult.View, vDic, vTemp, TextWriter.Null);
            try { viewResult.View.Render(viewContext, TextWriter.Null); }
            catch { }
        }
    }
}

Microsoft提供了一個新模塊,它是IIS 8.0的一部分,它取代了之前的預熱模塊。 IIS 7.5的應用程序初始化模塊可單獨下載。

該模塊將創建一個預熱階段,您可以在其中指定在服務器開始接受請求之前必須完成的許多請求。 這些請求將以比您嘗試實現的更強大的方式執行和編譯所有視圖。

我已經回答了一個類似的問題,詳細介紹了如何在IIS 7.5上預熱ASP.NET MVC應用程序?

不能直接回答你的問題 ,但我認為你應該看一下David Ebbo 使用RazorGenerator預編譯MVC Razor視圖

這樣做的一個原因是為了避免在站點啟動時遇到任何運行時命中,因為在運行時沒有任何內容可以編譯。 這在具有許多視圖的站點中可能很重要。

問題不在於問題中的代碼,而在於執行代碼的時間。 將代碼移動到動作中可以讓我毫無問題地執行預熱步驟。 在我的情況下,我想我將在安裝系統配置后調用預熱操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM