OWIN отправляет статический файл для нескольких маршрутов

Я делаю SPA, который находится поверх ASP.Net WebAPI. Я жду возможности использовать историю HTML5, а не #/ для маршрутизации истории, но это создает проблему для диплинкинга, мне нужно убедиться, что / и /foo/bar возвращают один и тот же файл HTML (и мой JS будет отображать правильную часть SPA) .

Как заставить OWIN/Katana возвращать один и тот же HTML-файл для нескольких разных URL-адресов?


person Aaron Powell    schedule 01.12.2014    source источник
comment
Итак, вы хотите, чтобы любой URL-адрес, попадающий на сервер, обслуживал index.html с использованием промежуточного ПО для статических файлов?   -  person khellang    schedule 02.12.2014
comment
Да, любой маршрут (или любой маршрут, соответствующий /app/*) вернет файл index.html.   -  person Aaron Powell    schedule 02.12.2014


Ответы (2)


Чтобы упростить задачу, сохраняя при этом все преимущества кэширования и т. д. из промежуточного программного обеспечения StaticFiles, я бы просто переписал путь запроса, используя встроенное промежуточное программное обеспечение, например

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Map("/app", spa =>
        {
            spa.Use((context, next) =>
            {
                context.Request.Path = new PathString("/index.html");

                return next();
            });

            spa.UseStaticFiles();
        });

        app.UseWelcomePage();
    }
}

Это будет обслуживать страницу приветствия на чем угодно, кроме /app/*, который всегда будет обслуживать index.html.

person khellang    schedule 02.12.2014
comment
Это не работает, когда вам также нужно обслуживать другие статические файлы (*.css, *.js и т. д.), необходимые для SPA. Вместо этого он возвращает index.html в качестве содержимого ответа. - person ryanulit; 10.04.2018
comment
Да, если вам нужно обслуживать другие статические ресурсы под /app, вам нужно включить какое-то условие перед заменой пути. Вы также можете добавить отдельный UseStaticFiles перед переопределением. Таким образом, он будет пытаться запросить index.html только в том случае, если предыдущие статические файлы MW не пройдут. - person khellang; 10.04.2018
comment
Я воспользовался вашей идеей и добавил еще один вызов UseStaticFiles, и, похоже, это помогло. Благодарю вас! - person ryanulit; 10.04.2018

Я столкнулся с аналогичной проблемой, используя Angular js, и использовал немного другой подход для решения проблемы.

Мы использовали Owin для отображения маршрута к точке входа в SPA (index.html). Это позволяет вам получить доступ к SPA и переходить на разные страницы. Однако, если вы когда-либо обновляли страницу, вы получали ошибку 404. По сути, маршрутизация AngularJS и маршрутизация Owin/Katana наступали друг другу на пятки.

Я решил проблему, создав собственный DelegatingHandler. Этот обработчик делегирования используется всякий раз, когда Owin/Katana не может найти маршрут, соответствующий запросу (404).

public class CustomDelegatingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Task<HttpResponseMessage> response = base.SendAsync(request, cancellationToken);
        if (response.Result.StatusCode == HttpStatusCode.NotFound)
        {
            response.Result.Content = new StringContent(File.ReadAllText(@"index.html"));
            response.Result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
            response.Result.StatusCode = HttpStatusCode.OK;
        }
        return response;
    }
}

Фрагмент выше возвращает index.html, точку входа SPA, когда мы не можем найти страницу, соответствующую запросу.

Чтобы использовать этот обработчик делегирования, вы должны добавить следующую строку в свой HttpConfiguration() при запуске хоста Owin:

        var httpConfig = new HttpConfiguration();
        httpConfig.MessageHandlers.Add(new CustomDelegatingHandler());

Короче говоря, у меня есть маршрут по умолчанию, который сопоставляется с SPA, и любой нераспознанный маршрут будет проходить через DelegatingHandler и обслуживать тот же SPA. Мы не изменяем Request.Path, позволяя SPA направлять запрос на нужную страницу.

person Justin    schedule 02.06.2016
comment
Это отчасти сработает, но во многих случаях будет целесообразно использовать такую ​​реализацию в продакшене. File.ReadAllText автоматически определит кодировку (что может вызвать проблемы) и будет не так эффективен, как другие подходы. - person Simon Opelt; 25.01.2017
comment
Спасибо за ваш вклад. Итак, вы предлагаете мне использовать решение, похожее на принятый ответ, или есть предпочтительная альтернатива File.ReadAllText? - person Justin; 26.01.2017