Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core map route to static file handler

I'm working on a ASP.NET Core website (previously named ASP.NET 5 / vNext) with Angular. In order for Angular to work I need to have a catch-all route:

app.UseStaticFiles(); 
app.UseMvc(routes =>
        {
            // Angular fallback route
            routes.MapRoute("angular", "{*url}", new { controller = "Home", action = "Index" });                
        });

I also have a few files/folders in wwwroot, like:

wwwroot/app
wwwroot/assets
wwwroot/lib

When any requests are made to these paths, for example http://example.com/assets/css/test.css, and the file (test.css) does NOT exist, it should not continue to the fallback route. It should return a 404.

Right now, if the file does not exist it returns the Angular HTML. So, how can I tell it that any path that starts with '/assets' should only be routed / served by UseStaticFiles?

like image 594
pbz Avatar asked Feb 23 '16 20:02

pbz


2 Answers

This seems to work:

app.MapWhen(
    context => {
        var path = context.Request.Path.Value.ToLower();
        return
            path.StartsWith("/assets") ||
            path.StartsWith("/lib") ||
            path.StartsWith("/app");
    },
    config => config.UseStaticFiles());

However, I'm not sure if there are any performance (or other type of) implications. I'll update if I come across any.

like image 197
pbz Avatar answered Sep 19 '22 08:09

pbz


It is strange that this common case (since many use SPA) is not covered almost anywhere and everyone has to invent something. I have found that the best way to do that is to add constraint (e.g. do not use the route if there is /api or "." in the path). Unfortunately this is not supported out of the box, but you can write this constraint yourself or copy the one I wrote from here.

There are a bit more details in this post. But generally the code looks like this:

 app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "api",
            template: "api/{controller}/{action}");

        routes.MapRoute(
            name: "angular",
            template: "{*url}",
            defaults: new {controller = "Home", action = "Index"},
            constraints: new {url = new DoesNotContainConstraint(".", "api/") });                
    });

P.S. Perhaps this constraint exist out of the box now, but I have not found one. Alternatively a RegEx can be used, but simple one should be way faster.

like image 30
Ilya Chernomordik Avatar answered Sep 19 '22 08:09

Ilya Chernomordik