.NET Core 2.0 MVC中如何将新建区域作为独立项目创建
嘿,我之前在.NET Core 2.0里拆分区域项目的时候也踩过这个路由歧义的坑,咱们一步步来把它解决掉!
1. 给区域控制器打上区域特性
这是最基础但也最容易遗漏的一步——你的区域项目里的所有控制器,必须加上[Area("你的区域名称")]特性,不然路由系统根本不知道它们属于哪个区域。比如:
[Area("Admin")] // 替换成你的实际区域名 public class DashboardController : Controller { public IActionResult Index() { return View(); } }
2. 调整主项目的路由配置顺序
.NET Core的路由匹配是从上到下按顺序匹配的,所以一定要把区域路由放在默认路由前面,不然默认路由会先匹配到主项目的控制器,导致歧义。在主项目的Startup.cs的Configure方法里这么写:
app.UseMvc(routes => { // 先配置区域路由,{area:exists}确保只匹配存在的区域 routes.MapRoute( name: "area_default", template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); // 再配置主项目的默认路由 routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
这里的{area:exists}是关键,它会过滤掉不存在的区域请求,避免和主项目的路由冲突。
3. 确认区域项目的项目类型
别用普通的.NET Core类库!区域项目必须是Web类库,也就是.csproj文件里的Sdk是Microsoft.NET.Sdk.Web,而不是普通的Microsoft.NET.Sdk。如果是普通类库,路由系统无法正确识别里面的控制器和区域配置。你的区域项目.csproj应该长这样:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <!-- 添加必要的MVC依赖 --> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" /> </ItemGroup> </Project>
4. 解决控制器名称重复的歧义
如果主项目和区域项目里有同名的控制器(比如都叫HomeController),哪怕加了区域特性,还是可能出现歧义。这时候可以给路由加上命名空间限定,明确指定每个路由应该匹配哪个项目下的控制器:
app.UseMvc(routes => { routes.MapRoute( name: "area_default", template: "{area:exists}/{controller=Home}/{action=Index}/{id?}", namespaces: new[] { "你的区域项目命名空间.Controllers" }); // 例如"AdminArea.Controllers" routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}", namespaces: new[] { "你的主项目命名空间.Controllers" }); // 例如"MainWebApp.Controllers" });
这样路由系统就会优先匹配指定命名空间下的控制器,不会再混淆了。
5. 启用路由调试排查问题
如果还是不行,咱们可以打开路由调试功能,看看请求到底匹配到了哪些路由。在主项目的Startup.cs的ConfigureServices里添加:
services.AddMvc(options => { options.RouteDebugger.Enabled = true; // 启用路由调试 });
然后访问你的区域URL(比如/Admin),页面会显示所有匹配的路由规则,你就能清楚看到哪里出了冲突。
按照这些步骤一步步来,应该就能解决那个“Ambiguous URLs”的错误了!
内容的提问来源于stack exchange,提问作者S.K.

