title: How to intercept 404 using Owin middleware
body: <h2>Background</h2>
  
  <p>First let me explain the background. I am working on a project that attempts to marry a backend server that uses Web API configured via OWIN- hosted on IIS now, but potentially other OWIN-supported hosts in the future- to a frontend using AngularJS.</p>
  
  <p>The AngularJS frontend is entirely static content. I completely avoid server-side technologies such as MVC/Razor, WebForms, Bundles, anything that has to do with the frontend and the assets it uses, and defer instead to the latest and greatest techniques using Node.js, Grunt/Gulp, etc. to handle CSS compilation, bundling, minification, etc. For reasons I won't go into here, I keep the frontend and server projects in separate locations within the same project (rather than stick them all in the Host project directly (see crude diagram below).</p>
  
  <pre><code>MyProject.sln
  server
    MyProject.Host
       MyProject.Host.csproj
       Startup.cs
       (etc.)
  frontend
    MyProjectApp
       app.js
       index.html
       MyProjectApp.njproj
       (etc.)
  </code></pre>
  
  <p>So as far as the frontend is concerned, all I need to do is get my Host to serve my static content. In Express.js, this is trivial. With OWIN, I was able to do this easily using <a href="https://www.nuget.org/packages/Microsoft.Owin.StaticFiles/" rel="nofollow noreferrer">Microsoft.Owin.StaticFiles</a> middleware, and it works great (it's very slick).</p>
  
  <p>Here is my <code>OwinStartup</code> configuration:</p>
  
  <pre><code>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);
  </code></pre>
  
  <h2>The Catch</h2>
  
  <p>Basically, it just hosts everything in <code>frontend/MyProjectApp</code> as if it were right inside the root of MyProject.Host. So naturally, if you request a file that doesn't exist, IIS generates a 404 error.</p>
  
  <p>Now, because this is an AngularJS app, and it supports <a href="https://docs.angularjs.org/guide/$location#html5-mode" rel="nofollow noreferrer"><code>html5mode</code></a>, I will have some routes that aren't physical files on the server, but are handled as routes in the AngularJS app. If a user were to drop onto an AngularJS (anything other than <code>index.html</code> or a file that physically exists, in this example), I would get a 404 even though that route might be valid in the AngularJS app. Therefore, I need my OWIN middleware to return the <code>index.html</code> file in the event a requested file does not exist, and let my AngularJS app figure out if it really is a 404. </p>
  
  <p>If you're familiar with SPAs and AngularJS, this is a normal and straight-forward approach. If I were using MVC or ASP.NET routing, I could just set the default route to an MVC controller that returns my <code>index.html</code>, or something along those lines. However, I've already stated I'm not using MVC and I'm trying to keep this as simple and lightweight as possible.</p>
  
  <p><a href="https://stackoverflow.com/questions/25916851/wrapping-staticfilemiddleware-to-redirect-404-errors">This user</a> had a similar dilemma and solved it with IIS rewriting. In my case, it doesn't work because a) my content doesn't physically exist where the rewrite URL module can find it, so it <em>always</em> returns <code>index.html</code> and b) I want something that doesn't rely on IIS, but is handled within OWIN middleware so it can be used flexibly.</p>
  
  <h2>TL;DNR me, for crying out loud.</h2>
  
  <p>Simple, how can I intercept a 404 Not Found and return the content of (note: <em>not</em> redirect) my <code>FileServer</code>-served <code>index.html</code> using OWIN middleware?</p>