Building A Simple File Server With OWIN and Katana

Monday, February 10, 2014

I have a scenario where I want to serve up HTML, JavaScript, and CSS files over HTTP from a .NET desktop application. This is the type of scenario Katana makes easy. Here is an example using a console application.

First, use NuGet to install a couple packages into the project.

install-package Microsoft.Owin.StaticFiles
install-package Microsoft.Owin.SelfHost

The source for the entire application is 17 lines of code, including using statements.

using System;
using Microsoft.Owin.Hosting;
using Owin;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var url = "http://localhost:8080";
            WebApp.Start(url, builder => builder.UseFileServer(enableDirectoryBrowsing:true));            
            Console.WriteLine("Listening at " + url);
            Console.ReadLine();
        }
    }
}

The FileServer middleware will serve files from the same directory as the executable.

Static Files With OWIN and Katana

If you don’t want to use the default location, you can provide your own IFileSystem and serve files from anywhere. Katana currently provides two implementations of IFileSystem – one to serve embedded resources and one to serve files from the physical file system. You can construct a PhysicalFileSystem for an arbitrary location on the hard drive.

static void Main(string[] args)
{
    var url = "http://localhost:8080";
    var root = args.Length > 0 ? args[0] : ".";
    var fileSystem = new PhysicalFileSystem(root);

    var options = new FileServerOptions
    {
        EnableDirectoryBrowsing = true, 
        FileSystem = fileSystem                             
    };

    WebApp.Start(url, builder => builder.UseFileServer(options));            
    Console.WriteLine("Listening at " + url);
    Console.ReadLine();
}

The FileServer middleware is actually a composite wrapper around three other pieces of middleware – DefaultFiles (to select a default.html file, if present, when a request arrives for a directory), DirectoryBrowser (to list the contents of a directory if no default file is found), and StaticFile (to reply with the contents of a file in the file system). All three pieces of middleware are configurable through the UseFileServer extension method.

For example, the static file middleware will only serve files with a known content type. Although the list of known content types is extensive, you might need to serve files with uncommon extensions, in which case you can plug a custom  IContentTypeProvider into the static files middleware.

public class CustomContentTypeProvider : FileExtensionContentTypeProvider
{
    public CustomContentTypeProvider()
    {
        Mappings.Add(".nupkg", "application/zip");
    }
}

Now the final program looks like the following.

static void Main(string[] args)
{
    var url = "http://localhost:8080";
    var root = args.Length > 0 ? args[0] : ".";
    var fileSystem = new PhysicalFileSystem(root);
    var options = new FileServerOptions();
    
    options.EnableDirectoryBrowsing = true;
    options.FileSystem = fileSystem;         
    options.StaticFileOptions.ContentTypeProvider = new CustomContentTypeProvider();

    WebApp.Start(url, builder => builder.UseFileServer(options));            
    Console.WriteLine("Listening at " + url);
    Console.ReadLine();
}

Comments
gravatar Morteza Tuesday, February 11, 2014
Hi Scott, Thanks for your post. I followed your post about 'Owin & Katana' (And other .Net posts from odetocode.com) but, I cannot understand when I should Owin & Katana. Can you help me, what is difference between Owin approach and IIS Approach?
gravatar scott Tuesday, February 11, 2014
@Morteza: IIS is still the primary host for most web applications. It provides all sorts of features that you can configure 1,000 different ways. Katana is great for making a web server out of an existing desktop application (WPF, Windows service, console application). It's also extremely lean and easy to apply and update individual components and only the components you need, if you want it to be the host for a web application hosted on a server.
gravatar Morteza Tuesday, February 11, 2014
Thanks for your replay.
gravatar HackPoint Wednesday, February 12, 2014
Hi Scott, I'm very familiar with your work and I'm very eager to say it's great! I have a question, can I use the Katana in Apache server? If so can you show some post for this.
gravatar scott Sunday, February 16, 2014
@HackPoint - I don't believe so, but I don't want to say it is impossible since I don't know all the extensibility points in Apache.
gravatar Bibhu Sunday, February 23, 2014
Thanks Scott. Its a good demo of usage of OWIN components.
gravatar Todd Monday, March 17, 2014
Hi Scott, I’ve been banging my head against the wall on this one and hoping to get some help, I watched your PluralSight video on MVC 5 fundamentals which was extremely helpful so thank you for that but still struggling a little bit, I have a MVC 5 application using Individual user Accounts for authentication and what I’m trying to achieve is restrict access to static files to only authenticated users, so i.e. if I’m authenticated I’d be able to get to the file /UserFiles/someImg.png but if I wasn’t authenticated I wouldn’t be able to. In previous versions of MVC I’d create the web.config file and place it in the UserFiles dir but that doesn’t seem possible with the new security model in MVC 5. Thanks
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!