在控制器外部的ApplicationStarted事件中使用ASP.NET Core 2.1 UrlHelper来预热Kestrel

时间:2019-01-02 17:50:12

标签: c# asp.net-core dependency-injection asp.net-core-mvc asp.net-core-2.1

IApplicationLifetime.ApplicationStarted事件尝试different things中构建MVC url总是会结束异常。例如

    public void ConfigureServices(IServiceCollection services) {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLife, IServiceProvider serviceProvider) {
        appLife.ApplicationStarted.Register(() => {
            var helperFactory = serviceProvider.GetService<IUrlHelperFactory>();
            var ctx = serviceProvider.GetService<IActionContextAccessor>();
        });
    }
  

System.ObjectDisposedException:“无法访问已处置的对象。”

IActionContextAccessor似乎是问题所在:由于我们不在http请求中,因此没有ActionContext可用。将IActionContextAccessor直接注入Configure时,我得到了一个对象。但是它的属性ActionContext为null,这是UrlHelper构造函数所必需的:

var helper = new UrlHelper(actionContext.ActionContext);

由于这些上下文仅需要有关路由的信息,因此我尝试使用路由创建某种假上下文

    IRouter localRoutes;
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLife, IServiceProvider serviceProvider) {
        appLife.ApplicationStarted.Register(() => {
            var routeData = new RouteData();
            routeData.PushState(localRoutes, new RouteValueDictionary(), new RouteValueDictionary());

            var urlHelperFactory = app.ApplicationServices.GetRequiredService<IUrlHelperFactory>();
            IUrlHelper helper = urlHelperFactory.GetUrlHelper(
                new ActionContext(
                    new DefaultHttpContext(),
                    routeData,
                    new ActionDescriptor() { })
            );

            string url = helper.Action("Index", "Home");
        });

        app.UseMvc(routes => {
            routes.MapRoute(
                name: "default",
                template: "{controller=Dashboard}/{action=Index}/{id?}");
            localRoutes = routes.Build();
        });
    }

helper.Action调用中会产生一些异常:

  

System.ArgumentNullException:“值不能为null。”

不知道该如何解决。我不想手动生成网址,因为更改需要应用于多个地方。

背景:应用程序预热

我的ASP.NET Core 2应用在启动后需要花费几秒钟来满足第一个请求,而随后的请求很快。由于这对于用户体验来说是不可接受的,因此我想预热我的应用程序。

旧的4.x IIS堆栈具有preloadEnabled,这正是我需要的:

  

指定IIS模拟用户请求到应用程序或虚拟目录的默认页面,以便对其进行初始化。 [...]

可悲的是,似乎新的Kestrel网络服务器也没有这样的选项,它也可以在Linux上运行。因此,我想通过发出2-3个请求来自己实现这样的事情。

0 个答案:

没有答案