Como interceptar 404 usando o middleware Owin

fundo

Primeiro, deixe-me explicar o plano de fundo. Estou trabalhando em um projeto que tenta se casar com um servidor back-end que usa a API da Web configurada via OWIN hospedada no IIS agora, mas potencialmente outros hosts suportados pelo OWIN no futuro - para um front-end usando o AngularJS.

O front end do AngularJS é um conteúdo totalmente estático. Evito completamente as tecnologias do lado do servidor, como MVC / Razor, WebForms, Bundles, qualquer coisa que tenha a ver com o frontend e os ativos que ele usa, e adiei para as melhores e mais recentes técnicas usando Node.js, Grunt / Gulp, etc. Por motivos que não abordarei aqui, mantenho os projetos frontend e server em locais separados no mesmo projeto (em vez de colocá-los todos no projeto Host diretamente (consulte o artigo diagrama abaixo).

MyProject.sln
server
  MyProject.Host
     MyProject.Host.csproj
     Startup.cs
     (etc.)
frontend
  MyProjectApp
     app.js
     index.html
     MyProjectApp.njproj
     (etc.)

No que diz respeito ao front-end, tudo o que preciso fazer é fazer com que meu host atenda meu conteúdo estático. No Express.js, isso é trivial. Com o OWIN, eu pude fazer isso facilmente usandoMicrosoft.Owin.StaticFiles middleware e funciona muito bem (é muito liso).

Aqui está o meuOwinStartup configuração:

string dir = AppDomain.CurrentDomain.RelativeSearchPath; // get executing path
string contentPath = Path.GetFullPath(Path.Combine(dir, @"../../../frontend/MyProjectApp")); // resolve nearby frontend project directory

app.UseFileServer(new FileServerOptions
{
    EnableDefaultFiles = true,
    FileSystem = new PhysicalFileSystem(contentPath),
    RequestPath = new PathString(string.Empty) // starts at the root of the host
});

// ensure the above occur before map handler to prevent native static content handler
app.UseStageMarker(PipelineStage.MapHandler);
A pegada

Basicamente, ele apenas hospeda tudo emfrontend/MyProjectApp como se estivesse dentro da raiz do MyProject.Host. Então, naturalmente, se você solicitar um arquivo que não existe, o IIS gerará um erro 404.

Agora, porque este é um aplicativo AngularJS e suportahtml5mode, Terei algumas rotas que não são arquivos físicos no servidor, mas são tratadas como rotas no aplicativo AngularJS. Se um usuário cair em um AngularJS (algo diferente deindex.html ou um arquivo que exista fisicamente, neste exemplo), eu receberia um 404 mesmo que essa rota seja válida no aplicativo AngularJS. Portanto, preciso do meu middleware OWIN para retornar oindex.html arquivo no caso de um arquivo solicitado não existir e deixe meu aplicativo AngularJS descobrir se realmente é um 404.

Se você conhece os SPAs e o AngularJS, essa é uma abordagem normal e direta. Se eu estivesse usando o roteamento MVC ou ASP.NET, eu poderia apenas definir a rota padrão para um controlador MVC que retorne meuindex.html, Ou algo nesse sentido. No entanto, eu já afirmei que não estou usando o MVC e estou tentando manter isso o mais simples e leve possível.

Este usuário teve um dilema semelhante e o resolveu com a reescrita do IIS. No meu caso, ele não funciona porque: a) meu conteúdo não existe fisicamente onde o módulo de URL de reescrita pode encontrá-lo;sempre retornaindex.html eb) quero algo que não dependa do IIS, mas que seja tratado no middleware OWIN para que possa ser usado com flexibilidade.

TL; DNR me, pelo amor de Deus.

Simples, como posso interceptar um 404 não encontrado e retornar o conteúdo de (nota:não redirecionar) meuFileServer-servidoindex.html usando o middleware OWIN?

questionAnswers(4)

yourAnswerToTheQuestion