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

如何将Application Parts中的控制器映射到子路径?

给ASP.NET Core模块端点设置独立子路径的实现方案

要给每个基于Application Parts的模块设置独立的子路径前缀,有几种实用的方案,根据你的场景选就行:

方案一:利用区域(Area)结合Application Parts

这是最直接的方式,把每个模块对应一个Area,通过区域路由统一设置前缀:

  1. 模块控制器标记Area
    在模块的所有控制器上添加[Area]特性,指定模块名称:
[Area("OrderModule")]
public class OrderController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}
  1. 配置区域路由
    在Program.cs中添加区域路由模板,让所有该Area下的控制器自动带上子路径前缀:
var builder = WebApplication.CreateBuilder(args);

// 加载模块的Application Parts
builder.Services.AddControllersWithViews()
    .AddApplicationPart(typeof(OrderModule.OrderController).Assembly);

var app = builder.Build();

// 配置区域路由
app.MapControllerRoute(
    name: "areaRoute",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.Run();

这样OrderModule下的所有端点都会自动映射到/OrderModule/xxx路径。

方案二:自定义路由约定统一添加前缀

如果不想用Area,可以通过自定义路由约定,给指定模块的控制器批量添加路由前缀:

  1. 创建自定义路由约定
    实现IApplicationModelConvention,给目标程序集的控制器添加前缀:
public class ModuleRouteConvention : IApplicationModelConvention
{
    private readonly string _routePrefix;
    private readonly Assembly _moduleAssembly;

    public ModuleRouteConvention(string routePrefix, Assembly moduleAssembly)
    {
        _routePrefix = routePrefix;
        _moduleAssembly = moduleAssembly;
    }

    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            // 只处理目标模块的控制器
            if (controller.ControllerType.Assembly == _moduleAssembly)
            {
                // 给控制器添加路由前缀
                controller.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        Template = $"{_routePrefix}/{controller.ControllerName}"
                    }
                });
            }
        }
    }
}
  1. 注册约定并加载Application Parts
    在Program.cs中注册这个约定,并关联对应的模块程序集:
var builder = WebApplication.CreateBuilder(args);

var orderModuleAssembly = typeof(OrderModule.OrderController).Assembly;

builder.Services.AddControllersWithViews()
    .AddApplicationPart(orderModuleAssembly)
    .AddMvcOptions(options =>
    {
        // 添加自定义路由约定,设置前缀为/Order
        options.Conventions.Add(new ModuleRouteConvention("Order", orderModuleAssembly));
    });

var app = builder.Build();

app.MapControllers();

app.Run();

这种方式下,OrderModule的控制器端点会映射到/Order/xxx路径。

方案三:用MapWhen隔离模块路由

如果需要更彻底的隔离(比如不同模块用不同的路由规则),可以用MapWhen创建独立的路由分支:

var builder = WebApplication.CreateBuilder(args);

// 先注册共享服务
builder.Services.AddControllersWithViews();

var app = builder.Build();

// 处理OrderModule的请求
app.MapWhen(context => context.Request.Path.StartsWithSegments("/Order"), orderApp =>
{
    // 在分支中加载模块的Application Parts并配置路由
    orderApp.UseRouting();
    orderApp.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers()
            .AddApplicationPart(typeof(OrderModule.OrderController).Assembly);
    });
});

// 处理其他模块或主应用的请求
app.MapControllers();

app.Run();

这种方式下,所有以/Order开头的请求都会被路由到OrderModule的控制器,且可以给不同分支设置独立的中间件或路由规则。

内容的提问来源于stack exchange,提问作者Pavel Voronin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 23:15:18