You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置ASP.NET Core路由:解决Angular 5部署Azure后深层链接404问题

解决ASP.NET Core MVC与Angular 5.x部署到Azure后的路由冲突问题

这个问题我之前部署ASP.NET Core+Angular的时候也碰到过,核心原因就是部署后所有请求都走ASP.NET Core的路由管道,而Angular的深层链接(比如/events/123)会被ASP.NET Core当成不存在的API路由返回404。下面是具体的解决步骤:

1. 确保静态文件中间件正确配置

首先要让ASP.NET Core能正确服务Angular编译后的静态资源(JS、CSS、图片等)。在Startup.cs的Configure方法中,先添加静态文件中间件:

using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.FileProviders;

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... 其他中间件(比如异常处理、HSTS等)

    // 服务Angular编译后的静态资源
    // 如果你的Angular dist目录直接放在ASP.NET Core的wwwroot下,直接用下面这行
    app.UseStaticFiles();

    // 如果Angular项目在ClientApp目录,编译后的dist在ClientApp/dist,用下面的配置:
    // app.UseStaticFiles(new StaticFileOptions
    // {
    //     FileProvider = new PhysicalFileProvider(
    //         Path.Combine(Directory.GetCurrentDirectory(), "ClientApp", "dist")),
    //     RequestPath = ""
    // });
}

2. 优先处理API路由

接下来要确保所有/api/*开头的请求被ASP.NET Core的MVC控制器正确处理。根据你的ASP.NET Core版本,配置路由:

方式一:使用端点路由(推荐,ASP.NET Core 3.0+)

app.UseRouting();

// 如果有授权中间件,放在这里
// app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    // 匹配所有/api开头的控制器路由
    endpoints.MapControllerRoute(
        name: "api",
        pattern: "api/{controller=Home}/{action=Index}/{id?}");
    
    // 如果你用的是属性路由(比如控制器上标记[Route("api/[controller]")]),可以直接用:
    // endpoints.MapControllers();
});

方式二:传统MVC路由(ASP.NET Core 2.x)

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

3. 添加Fallback路由,转发非API请求到Angular

这是最关键的一步:让所有不是/api开头的请求都返回Angular的index.html,这样Angular的路由就能接管这些请求了。

方式一:用自定义中间件(灵活可控)

在API路由配置之后添加这段代码:

// 所有非/api开头的请求,返回Angular的index.html
app.MapWhen(context => !context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
    appBuilder.Use(async (context, next) =>
    {
        // 确保返回正确的HTML内容类型
        context.Response.ContentType = "text/html";
        // 根据你的index.html实际路径调整
        var indexPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html");
        // 如果是ClientApp/dist下的index.html,路径改成:
        // var indexPath = Path.Combine(Directory.GetCurrentDirectory(), "ClientApp", "dist", "index.html");
        await context.Response.SendFileAsync(indexPath);
    });
});

方式二:用UseSpa中间件(官方推荐的SPA集成方式)

如果你是用官方的SPA模板创建的项目,或者希望更简洁的配置,可以用UseSpa:

app.UseSpa(spa =>
{
    // 指定Angular项目的根目录
    spa.Options.SourcePath = "ClientApp";

    // 部署环境下不需要启动Angular开发服务器,直接指向编译后的dist目录
    spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "ClientApp", "dist"))
    };

    // 所有非API请求都返回index.html
    spa.Options.DefaultPage = "/index.html";
});

4. 额外注意事项

  • Angular路由模式:确保Angular使用默认的PathLocationStrategy(这是默认配置,不需要额外修改),如果之前改成了HashLocationStrategy,深层链接不会有问题,但URL会带#,如果要去掉#就保持默认策略。
  • 部署时复制Angular编译文件:在ASP.NET Core的.csproj文件中添加以下配置,确保发布时自动编译Angular并将dist文件复制到发布目录:
<Target Name="PublishAngular" AfterTargets="ComputeFilesToPublish">
  <Exec Command="npm install" WorkingDirectory="ClientApp" />
  <Exec Command="ng build --prod" WorkingDirectory="ClientApp" />
  <ItemGroup>
    <DistFiles Include="ClientApp\dist\**" />
    <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
      <RelativePath>%(DistFiles.RecursiveDir)%(DistFiles.Filename)%(DistFiles.Extension)</RelativePath>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </ResolvedFileToPublish>
  </ItemGroup>
</Target>

这样配置之后,部署到Azure后,/api/event/{id}这类API请求会被ASP.NET Core处理,而Angular的深层链接(比如/events/123)会被转发到Angular的index.html,由Angular路由来处理,就不会出现404了。

内容的提问来源于stack exchange,提问作者Ralf de Kleine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:25:06