OWIN send static file for multiple routes

2019-03-11 05:40发布

问题:

I'm making a SPA which sits on top of ASP.Net WebAPI. I'm waiting to use HTML5 history rather than #/ for history routing but that poses a problem for deep linking, I need to make sure / and /foo/bar all return the same HTML file (and my JS will render the right part of the SPA).

How do I get OWIN/Katana to return the same HTML file for multiple different urls?

回答1:

To make things simple, while still keeping all the caching goodness etc. from the StaticFiles middleware, I'd just rewrite the request path using an inline middleware, like this

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();
    }
}

This will serve the welcome page on anything but /app/*, which will always serve index.html instead.



回答2:

I encountered a similar issue using Angular js, and used a slightly different approach to resolve the issue.

We used Owin to map a route to the entry point of the SPA (index.html). This allows you to access the SPA and navigate to the different pages. However, if you ever refreshed the page you would get a 404. Essentially, AngularJS's routing and Owin/Katana's routing were stepping on each others toes.

I resolved the issue by creating a custom DelegatingHandler. This delegating handler is used whenever Owin/Katana is unable to find a route matching the request (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;
    }
}

The snippet above returns index.html, the entry point of the SPA, when we are unable to find a page matching the request.

In order to use this delegating handler, you must add the following line to your HttpConfiguration() when starting the Owin host:

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

In short, I have a default route that maps to the SPA, and any unrecognized route will go through the DelegatingHandler and serve the same SPA. We do not modify the Request.Path, allowing the SPA to route the request to the proper page.