Configure an OWIN static file server at a specific route prefix

George Mauer picture George Mauer · Jun 7, 2014 · Viewed 8.2k times · Source

I'm experimenting with keeping my content in non-default locations (eg in bower_components or /packages/../tools). As part of the experiment I am trying to set up an asp.net mvc 5 application where hitting a certain route allows me to browse files in the undersorejs package directory.

I have the following nuget packages (in addition to the default)

Install-Package underscore.js
Install-Package Microsoft.Owin.StaticFiles
Install-Package Microsoft.Owin.Host.SystemWeb

This is what I have in an OWIN startup class

 var fileSystem = new PhysicalFileSystem(
                    HttpContext.Current.Server.MapPath("~")+"/../packages/underscore.js.1.6.0"
                  );
 var options = new FileServerOptions {EnableDirectoryBrowsing = true, FileSystem = fileSystem};

 app.MapWhen(ctx => 
      ctx.Request.Uri.AbsolutePath.StartsWith("/__underscore"), 
      ab => ab.UseFileServer(options)
 );

To my understanding and previous experimentation this is pretty straightforward - when the request begins with /__underscore use the simple static file server. However when I head over to /__underscore I get a 404 error.

However, placing breakpoints I can see that the UseFileServer lambda executes once on startup and then never again, while the predicate lambda is called on every request (and returns the correct value).

What am I missing?

Answer

haim770 picture haim770 · Jun 8, 2014

You need to specify the RequestPath as well:

var options = new FileServerOptions {
                      EnableDirectoryBrowsing = true,
                      FileSystem = fileSystem,
                      RequestPath = PathString.FromUriComponent("/__underscore")
                      };

As per your comment:

If you're unable to download files, try to explicitly register OwinHttpHandler in your Web.Config:

<system.webServer> 
    <handlers> 
        <add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/> 
    </handlers> 
</system.webServer>

Alternatively, you can set runAllManagedModulesForAllRequests to 'true':

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="FormsAuthenticationModule" />
    </modules>
</system.webServer>