17

I've set up a web site using an Owin self hosted console app. I'm serving static files with no problem, the 'root' of the static part of the site works properly, and the web API routes work fine also.

If I browse to:

http://localhost/index.html

it presents everything like I expect. But I have not figured out how to set it so that browsing to:

http://localhost

presents index.html (as the default view). This Just Works under an IIS-style site. How do I make it work with Owin self host?

wilee
  • 601
  • 2
  • 6
  • 19

5 Answers5

21

I do it this way:

var physicalFileSystem = new PhysicalFileSystem(webPath);
var options = new FileServerOptions
                          {
                              EnableDefaultFiles = true,
                              FileSystem = physicalFileSystem
                          };
        options.StaticFileOptions.FileSystem = physicalFileSystem;
        options.StaticFileOptions.ServeUnknownFileTypes = true;
        options.DefaultFilesOptions.DefaultFileNames = new[] { "index.html" };
        appBuilder.UseFileServer(options);
fra
  • 3,488
  • 5
  • 38
  • 61
  • 1
    Has this changed since this post was written? I have exactly this and while I can go to `http://localhost:5000/index.html` and see the page, if I just go to `http://localhost:5000` I just get a 404. – Eddie Mar 02 '15 at 13:31
  • 1
    @Eddie this does work with all the latest versions of the NuGet packages. I think you will just need to add the correct relative file path for index.html. Mine is "app/templates/index.html" and this works when I enter http://localhost:8080/ into Chrome :) – JDTLH9 Mar 17 '15 at 15:19
  • 4
    @Eddie couple the above with making sure the html file is in the build location by setting its "Copy to Output Directory" property to "Copy Always" or "Copy if newer". It is a shame you do not get an exception if the file cannot be found!!! – JDTLH9 Mar 17 '15 at 17:19
  • @JDTLH9 Ah relative path! I was just writing "index.html" thinking it would find it. Cheers – Eddie Mar 17 '15 at 19:50
  • 1
    This doesn't seem to work if the root is not directly below the current path. If for instance root path is ..\\web it only manages to serve the default document, but all other references (.js, .css etc) returns 404, because it tries to resolve them below the path of the project that defines the appBuilder... Weird behaviour... – Yngve B-Nilsen Oct 27 '15 at 18:50
21

a more detailed version of fra's answer:

1- NuGet to install Microsoft.Owin.StaticFiles (I assumed you already installed Microsoft.AspNet.WebApi.OwinSelfHost via NuGet)

2- Create a single directory in your solution (in Visual Studio), and put all your client files in it, e.g.

+Web

--+images

--+pages

------page1

------page2

--+scripts

--+css

---index.html

Note: there is a root directory (web) that contains all other directories, and the index.html under the root directly.

3- Now, in the same class that contains your web api routing configuration, add the following code:

var physicalFileSystem = new PhysicalFileSystem(@".\Web"); //. = root, Web = your physical directory that contains all other static content, see prev step
var options = new FileServerOptions
{
    EnableDefaultFiles = true,
    FileSystem = physicalFileSystem
 };
 options.StaticFileOptions.FileSystem = physicalFileSystem;
 options.StaticFileOptions.ServeUnknownFileTypes = true;
 options.DefaultFilesOptions.DefaultFileNames = new[] { "index.html" }; //put whatever default pages you like here
 appBuilder.UseFileServer(options);

4- One more step for the prev code to work: make sure to set the Copy to output directory property of all files in Web directory (and all nested directories) is set to Copy Always [select the file | press F4, or right-click then properties | go to Copy to output directory]

That's all :)

Sameh Deabes
  • 2,960
  • 25
  • 30
7

Maybe it's a late answer, but if you need just a default document, less code will work:

builder.UseDefaultFiles(new DefaultFilesOptions
{
    DefaultFileNames = Enumerable.Repeat("index.html", 1).ToList()
});

It should be called before builder.UseStaticFiles for whatever reason.

Version of Microsoft.Owin.StaticFiles is 3.0.1

the_joric
  • 11,986
  • 6
  • 36
  • 57
3

Maybe this late answer could help any other :) I just had the same problem with a SelfHost Owin app.

The solution I found is implementing a class from IFileSystem interface that encapsulates a PhysicalFileSystem class (which also implements from IFileSystem).

public class WebPhysicalFileSystem : IFileSystem
{
    private PhysicalFileSystem InnerFileSystem { get; set; }
    private string Default { get; set; }

    public WebPhysicalFileSystem(string root, string defaultFile = "index.html")
    {
        InnerFileSystem = new PhysicalFileSystem(root);
        Default = defaultFile;
    }

    public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents)
    {
        if(InnerFileSystem.TryGetDirectoryContents(subpath, out contents))
        {
            return true;
        }

        string defaultPath = System.IO.Path.Combine(InnerFileSystem.Root, Default);
        return InnerFileSystem.TryGetDirectoryContents(defaultPath, out contents);
    }

    public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo)
    {
        if (InnerFileSystem.TryGetFileInfo(subpath, out fileInfo))
        {
            return true;
        }

        string defaultPath = System.IO.Path.Combine(InnerFileSystem.Root, Default);
        return InnerFileSystem.TryGetFileInfo(defaultPath, out fileInfo);
    }
}

And in the app:

var options = new FileServerOptions
{
    EnableDefaultFiles = true,
    FileSystem = new WebPhysicalFileSystem("yourRoot");
};
  • this was very useful, I implemented a similar class that will server index.html so my spa works fine, I wish I could give you more upvotes – Alas Jul 31 '17 at 18:45
1

In my case, I was missing the

<handlers>
    <add name="AspNetStaticFileHandler" path="*" verb="*" type="System.Web.StaticFileHandler" />
</handlers>

In system.webServer part of my web.config.

Cubelaster
  • 338
  • 4
  • 6