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

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

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

Ответ 1

Чтобы сделать вещи простыми, сохраняя при этом все преимущества кеширования и т.д. из промежуточного программного обеспечения 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 вместо этого.

Ответ 2

Я столкнулся с аналогичной проблемой, используя 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 направить запрос на нужную страницу.