【问题标题】:Preload ASP.NET MVC views in IIS warmup step在 IIS 预热步骤中预加载 ASP.NET MVC 视图
【发布时间】:2011-10-03 11:18:48
【问题描述】:

我最近开始使用 IIS 的功能,通过使用 IProcessHostPreloadClient 接口将预热步骤步骤应用于我的 Web 应用程序(请查看 here 以获取有关如何设置的指导)。这效果很好,或者至少我认为它确实如此,因为我做的一件“聪明”的事情是尝试通过迭代我的控制器并渲染它们来预加载我的视图。

经过一些尝试和错误,我让它工作了,一切都很好。也就是说,直到我注意到我的系统的所有验证都不再有效,无论是客户端验证还是服务器验证。我假设当 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 { }
        }
    }
}

【问题讨论】:

    标签: c# .net asp.net-mvc warm-up


    【解决方案1】:

    不能直接回答你的问题,但我认为你应该看看 David Ebbo 的 Precompiling MVC Razor views using RazorGenerator

    这样做的一个原因是避免您的网站在运行时受到任何影响 开始,因为在运行时没有任何东西可以编译。这可以是 在有很多浏览量的网站中很重要。

    【讨论】:

    • 我使用了一些全局 Razor 辅助方法,但我无法让 Razor 生成器与它们一起使用。否则,它看起来是一个非常有用的工具。
    • 我不确定预编译视图是否值得。我认为新的 IIS 应用程序初始化及其对重叠进程回收的支持更好地解决了这个问题。
    【解决方案2】:

    问题不在于问题中的代码,而在于执行的时间。将代码移动到一个动作中可以让我毫无问题地执行预热步骤。就我而言,我想我只会在系统配置完成后让安装过程调用预热操作。

    【讨论】:

      【解决方案3】:

      有一个来自 Microsoft 的新模块,它是 IIS 8.0 的一部分,它取代了之前的预热模块。此Application Initialization Module for IIS 7.5 可单独下载。

      该模块将创建一个预热阶段,您可以在其中指定在服务器开始接受请求之前必须完成的请求数量。这些请求将以比您尝试实现的更强大的方式执行和编译您的所有视图。

      我已经在How to warm up an ASP.NET MVC application on IIS 7.5? 回答了类似的问题并提供了更多详细信息。

      【讨论】:

        猜你喜欢
        • 2011-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-17
        • 1970-01-01
        • 2015-11-02
        • 2023-03-04
        相关资源
        最近更新 更多