简体   繁体   English

ASP.NET Core 将路由映射到静态文件处理程序

[英]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.我正在使用 Angular 开发 ASP.NET Core 网站(以前称为 ASP.NET 5 / vNext)。 In order for Angular to work I need to have a catch-all route:为了让 Angular 正常工作,我需要有一个包罗万象的路线:

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 中也有一些文件/文件夹,例如:

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.当对这些路径发出任何请求时,例如http://example.com/assets/css/test.css ,并且文件 ( test.css ) 不存在,它不应继续回退路由。 It should return a 404.它应该返回 404。

Right now, if the file does not exist it returns the Angular HTML.现在,如果该文件不存在,它将返回 Angular HTML。 So, how can I tell it that any path that starts with '/assets' should only be routed / served by UseStaticFiles ?那么,我怎么能告诉它任何以 '/assets' 开头的路径只能由UseStaticFiles路由/提供?

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.如果我遇到任何我会更新。

It is strange that this common case (since many use SPA) is not covered almost anywhere and everyone has to invent something.奇怪的是,这种常见的情况(因为许多人使用 SPA)几乎没有涵盖任何地方,每个人都必须发明一些东西。 I have found that the best way to do that is to add constraint (eg do not use the route if there is /api or "." in the path).我发现最好的方法是添加约束(例如,如果路径中有 /api 或“.”,则不要使用路由)。 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/") });                
    });

PS Perhaps this constraint exist out of the box now, but I have not found one. PS 也许这个约束现在开箱即用,但我还没有找到。 Alternatively a RegEx can be used, but simple one should be way faster.或者,可以使用 RegEx,但简单的应该更快。

If you are using attribute template routing then you can apply this elegant solution:如果您使用的是属性模板路由,那么您可以应用这个优雅的解决方案:

[HttpGet("")]
[HttpGet("{*route:regex(^(?!skipped).*$)}")]
public async Task<IActionResult> Default(string route) { throw new NotImplementedException(); }

So all routes started with skipped will be ignored by this action.因此,此操作将忽略所有以skipped开头的路由。
If you want multiple prefixes or anything else then just update regex for your needs.如果您想要多个前缀或其他任何东西,那么只需根据您的需要更新正则表达式。
First Get attribute is needed to handle root of site (in this case route variable is null ).首先需要 Get 属性来处理站点的根目录(在这种情况下, route变量为null )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM