ASP.net核心MVC捕获所有路由服务静态文件

Mar*_*oxx 21 c# asp.net-core-mvc asp.net-core

有没有办法让catch所有路由都提供静态文件?

看看这个http://blog.nbellocam.me/2016/03/21/routing-angular-2-asp-net-core/

我基本上想要这样的东西:

        app.UseMvc(routes =>
        {
            routes.MapRoute("default", "{controller}/{action=Index}");

            routes.MapRoute("spa", "{*url}"); // This should serve SPA index.html
        });
Run Code Online (Sandbox Code Playgroud)

因此,任何与MVC控制器不匹配的路由都将起作用 wwwroot/index.html

Ben*_*son 34

我不得不为@DavidG做一些补充.这就是我最终的结果

Startup.cs

app.UseStaticFiles();

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller}/{action}");

   routes.MapRoute("Spa", "{*url}", defaults: new { controller = "Home", action = "Spa" });
});
Run Code Online (Sandbox Code Playgroud)

HomeController.cs

public class HomeController : Controller
{
  public IActionResult Spa()
  {
      return File("~/index.html", "text/html");
  }
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*idG 22

如果您已经处于路由阶段,那么您已经超越了管道中提供静态文件的位置.你的创业公司看起来像这样:

app.UseStaticFiles();

...

app.UseMvc(...);
Run Code Online (Sandbox Code Playgroud)

这里的顺序很重要.因此,您的应用程序将首先查找静态文件,这从性能角度来看是有意义的 - 如果您只想丢弃静态文件,则无需运行MVC管道.

您可以创建一个catch-all控制器操作,它将返回文件的内容.例如(窃取评论中的代码):

public IActionResult Spa()
{
    return File("~/index.html", "text/html");
}
Run Code Online (Sandbox Code Playgroud)

  • 我是一个傻瓜,忘了继承"控制器",这就是为什么我看不到它.谢谢! (3认同)
  • @Marcus 这不是文件类,而是控制器的 [`File`](https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.mvc.controllerbase#Microsoft_AspNetCore_Mvc_ControllerBase_File_System_String_System_String_) 方法班级。 (2认同)

Ost*_*ati 21

ASP.NET Core捕获Web API和MVC的所有路由的配置不同

使用Web API(if you're using prefix "api" for all server-side controllers eg. Route("api/[controller"]):

app.Use(async (context, next) => 
{ 
    await next(); 
    var path = context.Request.Path.Value;

    if (!path.StartsWith("/api") && !Path.HasExtension(path)) 
    { 
        context.Request.Path = "/index.html"; 
        await next(); 
    } 
});            

app.UseStaticFiles();
app.UseDefaultFiles();

app.UseMvc();
Run Code Online (Sandbox Code Playgroud)

使用MVC(dotnet add package Microsoft.AspNetCore.SpaServices -Version x.y.z):

app.UseStaticFiles();
app.UseDefaultFiles();

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

    routes.MapSpaFallbackRoute("spa", new { controller = "Home", action = "Index" }); 
});  
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 6

如果您不想手动指定 api 的路由:

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseMvc() // suggestion: you can move all the SPA requests to for example /app/<endpoints_for_the_Spa> and let the mvc return 404 in case <endpoints_for_the_Spa> is not recognized by the backend. This way SPA will not receive index.html

// at this point the request did not hit the api nor any of the files

// return index instead of 404 and let the SPA to take care of displaying the "not found" message
app.Use(async (context, next) => {
    context.Request.Path = "/index.html";
    await next();
});
app.UseStaticFiles(); // this will return index.html
Run Code Online (Sandbox Code Playgroud)


Nel*_*mel 5

我正在使用的效果很好的是Microsoft.AspNetCore.Builder.SpaRouteExtensions.MapSpaFallbackRoute

app.UseMvc(routes =>
{
    // Default route for SPA components, excluding paths which appear to be static files (have an extension)
    routes.MapSpaFallbackRoute(
        "spaFallback",
        new { controller = "Home", action = "Index" });
});
Run Code Online (Sandbox Code Playgroud)

HomeController.Index有相当于你的index.html. 您也可以路由到静态页面。

有点偏离主题,但如果您在同一项目中的api文件夹下也有 API,您可以为任何不匹配的 API 路由设置默认 404 响应:

routes.MapRoute(
    "apiDefault",
    "api/{*url}",
    new { controller = "Home", action = "ApiNotFound" });
Run Code Online (Sandbox Code Playgroud)

您最终会出现以下行为:

  • /controller=> 没有扩展,所以从 SPA 默认页面提供服务HomeController.Index并让 SPA 处理路由
  • /file.txt => 检测到扩展,提供静态文件
  • /api/controller => 正确的 API 响应(使用属性路由或为 API 控制器设置另一个映射)
  • /api/non-existent-route=> 404NotFound()返回HomeController.ApiNotFound

在许多情况下,您需要在单独的项目中使用 API,但这是一个可行的替代方案。