Используйте ASP.NET Core 2.1 UrlHelper в событии ApplicationStarted вне контроллеров для разогрева Kestrel - PullRequest
0 голосов
/ 02 января 2019

Построение URL-адресов MVC в IApplicationLifetime.ApplicationStarted событийном повторении разных вещей всегда заканчивалось исключениями. Например

    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 равно нулю, которое потребуется для конструктора 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: «Значение не может быть нулевым.»

Не знаю, как это исправить. Я не хочу создавать URL-адреса вручную, так как изменения должны применяться в нескольких местах.

Фон: прогрев приложения

Моему приложению ASP.NET Core 2 требуется несколько секунд для обработки первого запроса после запуска, где следующие запросы выполняются довольно быстро. Поскольку это неприемлемо для пользовательского опыта, я хочу прогреть свое приложение.

В старом стеке IIS 4.x есть preloadEnabled , именно то, что мне нужно:

Указывает, что IIS имитирует запрос пользователя к странице приложения или виртуального каталога по умолчанию для его инициализации. [...]

К сожалению, похоже, что нет такой опции для нового веб-сервера Kestrel, который также может работать в Linux. Поэтому я бы хотел реализовать что-то подобное самостоятельно, сделав 2-3 запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...