[英]ASP.NET MVC - Application warmup - which of two approaches to use?
[英]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.