配置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
相关产品推荐
相关产品推荐

