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 linkin
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.
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.