我最近開始使用IIS的能力,通過使用IProcessHostPreloadClient
接口向我的Web應用程序應用預熱步驟步驟(請參閱here以獲取有關如何設置此步驟的指導向上)。這個結果很好,或者至少我認爲它確實如此,因爲我做的「聰明」事情之一就是通過迭代我的控制器並渲染它們來嘗試並預裝我的視圖。在IIS預熱步驟中預加載ASP.NET MVC視圖
經過一些試驗和錯誤,我得到它的工作,一切都很好。也就是說,直到我發現我的系統的所有驗證不再有效,無論是客戶端還是服務器驗證。我假設驗證通常是在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 { }
}
}
}
我使用了一些全局Razor幫助器方法,我無法使Razor生成器與它們一起工作。否則,它看起來是一個非常有用的工具。 –
我不確定預編譯視圖是否值得付出。我認爲新的IIS應用程序初始化支持重疊流程回收,可以更好地解決問題。 –