8

How to serve static files for your Single Page Application from .NET Core

This article refers to project.json which Microsoft has deprecated in favour of a revamped .csproj file.

A new article will be published shortly and I’ll put a link here.

If you want to host your SPA app on .NET Core you’ll need to make sure your application is set up to serve your SPA’s static html and javascript files.

First of all make sure you’ve got a .NET Core web application up and running.

There are two ways to serve the initial page for your SPA.

1) Use a static html page
2) Use an MVC controller to return a view

If you want to use an MVC controller and a view, check out adding MVC to your ASP.NET Core web application.

Even if you do decide to use MVC to serve the view, you’ll still need to serve static files for your javascript. Read on to find out how.

Serving static files

Start off by creating a wwwroot folder in the root of your web app and create an index.html file inside it.

Update
Bastien rightly pointed out (in the comments) that this will already be set up and working if you used the ASP.NET/MVC template to create your Core app. If you’ve followed the previous posts and/or set up your Core app from scratch without using the template, then you’ll need to manually configure Core to serve static pages. Read on to see how.

If you run your app and try to access this index.html file you’re out of luck. The file will not be served.

By default ASP.NET Core does not serve static files. To change that you need to make a few changes.

Change your project.json to bring in the StaticFiles dependency.

{
  "version": "1.0.0-*",
  "buildOptions": {
    "preserveCompilationContext": true,
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        },
        "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
        "Microsoft.AspNetCore.Mvc": "1.0.0",
        "Microsoft.AspNetCore.StaticFiles": "1.0.0"
      },
      "imports": "dnxcore50"
    }
  }
}

Remember to run dotnet restore after adding dependencies.

Update the Configure method in Startup.cs to add the UseStaticFiles Middleware.

        public void Configure(IApplicationBuilder app)
        {
            app.UseMvc();
            app.UseStaticFiles();

            app.Run(context => {
                return context.Response.WriteAsync("Hello world");
            });
        }

Finally make sure you’ve specified a ContentRoot in Program.cs.

        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .Build();
 
            host.Run();
        }

By default the static files middleware will now serve static files contained within the wwwroot folder.

Run your app (dotnet run) and you’ll be able to access your static page in the browser.

http://localhost:5000/index.html

Note, you don’t need to put wwwroot in the url, in fact if you do, it won’t work.

You can now put any static files (css,js, images) in wwwroot and they will be accessible by your SPA.

  • Pingback: Dew Drop - August 26, 2016 (#2316) - Morning Dew()

  • bastien

    Why this post? In the asp.net template the .UseStaticFiles() is already declared and in use…

    • Jon Hilton

      Hey, thanks for your comment.

      That’s true, if you choose to use the template. If you choose to build a barebones app from scratch (as this series of posts did) then there’s a few things like this that are useful to know.

      Why would you choose to not use the template? Well that depends on whether you want to keep your app really lean and only bring in the bits you need, or accept some dependencies that you might never use in favour of less manual setup.

      As always, different solutions depending on your preference/requirements.

    • Hey, thanks for your comment.

      That’s true, if you choose to use the template. If you choose to build a barebones app from scratch (as this series of posts did) then there’s a few things like this that are useful to know.

      Why would you choose to not use the template? Well that depends on whether you want to keep your app really lean and only bring in the bits you need, or accept some dependencies that you might never use in favour of less manual setup.

      As always, different solutions depending on your preference/requirements.

    • Reading this again, the post didn’t make it clear why you’d need to set this up manually, have updated it to make it clearer.

      Thanks for the feedback!

  • Pingback: In the eyes of authority - and maybe rightly so - nothing looks more like a link than the ordinary man. - Agamben - Magnus Udbjørg()

  • Pingback: Szumma #055 – 2016 35. hét | d/fuel()

  • Florian Verdonck

    Thanks for this post, maybe include the using statements as well since this is an extension method.