How to serve index.html with web api selfhosted with OWIN
Asked Answered
C

2

32

Should be an easy question, just can't find the answer.

I have an SPA (AngularJS) with web api which is self hosted with Owin. I use Nancy to serve the page, but I would like to get rid of Nancy and use Index.html as my single page.

I've seen this question here: How to route EVERYTHING other than Web API to /index.html

I can't use accepted answer as I don't have MVC and HomeController, the way suggested in the updated question doesn't work either, I get No HTTP resource was found that matches the request URI 'http://admin.localhost:33333/'. No route providing a controller name was found to match request URI 'http://admin.localhost:33333/'

Cerebritis answered 12/2, 2015 at 11:54 Comment(0)
B
45

Move your Index.html to the root of your project. Then install-package Microsoft.Owin.StaticFiles in Package Manager Console and add the code below:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {

        const string rootFolder = ".";
        var fileSystem=new PhysicalFileSystem(rootFolder);
        var options = new FileServerOptions
                      {
                          EnableDefaultFiles = true,
                          FileSystem = fileSystem
                       };

        app.UseFileServer(options);

    }
}

This will serve up your Index.html by default.

You can checkout Scott Allen's blog for more reading:

http://odetocode.com/blogs/scott/archive/2014/02/10/building-a-simple-file-server-with-owin-and-katana.aspx

Ballon answered 14/2, 2015 at 15:50 Comment(2)
Thanks, this is very helpful. Just a suggestion: the package seems to be in plural form: Microsoft.Owin.StaticFilesUzzi
Can we use this technique to host both UI ( angular app ) and the WebApi in the same port? If yes then can you share the code? ThanksInnumerable
G
0

I recently had the same problem where i needed to serve a single page app (react in my case) and some api controllers from the same self hosted OWIN pipeline. The accepted answer works great to serve the client files, but it fails if your SPA uses client side routing.

If your SPA needs client side routing (i used react-router-dom), you need to redirect requests that don't map to files or api controllers to your index.html file. To do this, you can add a custom middleware at the end of your pipeline and use the SendFileAsync() method from Microsoft.Owin.StaticFiles to return index.html:

public class OwinPipeline
{
    public void Configuration(IAppBuilder appBuilder)
    {
        // SPA files from /wwwroot
        var opts = new FileServerOptions
        {
            EnableDefaultFiles = true,
            FileSystem = new PhysicalFileSystem("./wwwroot"),
        };
        appBuilder.UseFileServer(opts);

        // Web API
        var config = new HttpConfiguration
        {
            IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
        };
        config.MapHttpAttributeRoutes();
        appBuilder.UseWebApi(config);

        // Use index.html if not a file or controller route
        appBuilder.Use(async (context, _) =>
        {
            // If no middleware handled the request, send index.html.
            // this way the client side router can handle the route.
            await context.Response.SendFileAsync("./wwwroot/index.html");
        });
    }
}

There are two important points here:

  1. The middleware needs to be the last one in your pipeline. This way it only gets called when no other middleware matched the request.
  2. Don't call await next() in your last middleware as this would change the response code to a 404. This is a default behavior of the OWIN pipeline.

Note:

  • I placed my index.html and all other SPA files in a wwwroot folder in my project.
  • When you use a relativ path in SendFileAsync(), it uses Directory.GetCurrentDirectory() as base path to locate your file. If your web filesystem root differs from that, it throws a FileNotFound exception. In this case it might be necessary to provide the absolute path to your index.html file.
Goles answered 22/3, 2024 at 12:24 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.