C# 在IIS预热步骤中预加载ASP.NET MVC视图
最近,我开始玩弄IIS的能力,通过使用C# 在IIS预热步骤中预加载ASP.NET MVC视图,c#,.net,asp.net-mvc,warm-up,C#,.net,Asp.net Mvc,Warm Up,最近,我开始玩弄IIS的能力,通过使用IProcessHostPreloadClient界面,将预热步骤应用到我的web应用程序中(请查找有关如何设置此步骤的指导)。这很好,或者至少我认为是这样,因为我做的一件“聪明”的事情是通过迭代我的控制器并渲染它们来尝试和预加载我的视图 经过一点尝试和错误,我让它工作,一切都很好。也就是说,直到我注意到我的系统的所有验证都不再有效,无论是客户端验证还是服务器验证。我假设当MVC第一次检索视图时,验证通常连接到视图,但我没有这样做。有人知道如何将其包括在我的
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应用程序初始化及其对重叠进程回收的支持更好地解决了这个问题。