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

.NET 7 MVC应用中如何注册自定义IRouter?

方案可行性与注册步骤

首先,在.NET 7 MVC中使用自定义IRouter完全符合你的需求,是正确的技术方案。你的场景需要动态解析路由(从数据库映射短ID到控制器/动作)、权限与时效校验,且要隐藏底层路由结构,这正是自定义路由的典型适用场景,没有思路问题。

注册自定义IRouter的步骤

1. 注册自定义路由服务

先将你的自定义IRouter实现类注册到依赖注入容器中(假设你的实现类名为ShortUrlRouter,依赖数据库上下文等服务):

builder.Services.AddScoped<ShortUrlRouter>();

2. 配置路由优先级

在Program.cs的路由配置环节,将自定义路由添加到路由集合的最前面(路由匹配按顺序执行,短URL路由需要优先匹配),再配置默认MVC路由:

var app = builder.Build();

// ...其他中间件配置(如静态文件、认证授权等)...

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    // 注入自定义路由并添加到路由集合
    var shortUrlRouter = app.Services.GetRequiredService<ShortUrlRouter>();
    endpoints.Routes.Add(shortUrlRouter);

    // 配置默认MVC路由
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

自定义IRouter核心实现要点

确保你的RouteAsync方法完成以下关键逻辑:

public class ShortUrlRouter : IRouter
{
    private readonly IRouter _defaultRouter;
    private readonly AppDbContext _dbContext;

    public ShortUrlRouter(IRouter defaultRouter, AppDbContext dbContext)
    {
        _defaultRouter = defaultRouter;
        _dbContext = dbContext;
    }

    public async Task RouteAsync(RouteContext context)
    {
        var shortId = context.HttpContext.Request.Path.Value.Trim('/');
        // 跳过空路径或已有层级的路径,交给默认路由处理
        if (string.IsNullOrEmpty(shortId) || shortId.Contains('/'))
        {
            await _defaultRouter.RouteAsync(context);
            return;
        }

        // 从数据库查询短ID对应的路由映射
        var mapping = await _dbContext.ShortUrlMappings
            .FirstOrDefaultAsync(m => m.ShortId == shortId);

        if (mapping == null)
        {
            await _defaultRouter.RouteAsync(context);
            return;
        }

        // 校验访问时效与用户权限
        if (mapping.ExpiresAt < DateTime.UtcNow || !IsAuthorized(context.HttpContext.User, mapping.AllowedRoles))
        {
            context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
            return;
        }

        // 设置路由数据,指向目标控制器与动作
        context.RouteData.Values["controller"] = mapping.TargetController;
        context.RouteData.Values["action"] = mapping.TargetAction;
        // 如有必要,添加额外路由参数
        // context.RouteData.Values["targetId"] = mapping.TargetId;

        // 交给默认路由处理后续请求
        await _defaultRouter.RouteAsync(context);
    }

    // 实现GetVirtualPath方法,支持生成短URL(你已实现此部分,确保逻辑正确即可)
    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        // 你的短URL生成逻辑,比如根据控制器/动作反向生成短ID
        // 示例:
        if (context.Values.TryGetValue("controller", out var controller) &&
            context.Values.TryGetValue("action", out var action))
        {
            var mapping = _dbContext.ShortUrlMappings
                .FirstOrDefault(m => m.TargetController == controller.ToString() 
                                    && m.TargetAction == action.ToString());
            if (mapping != null)
            {
                return new VirtualPathData(this, $"/{mapping.ShortId}");
            }
        }
        // 无匹配时返回null,交给默认路由生成URL
        return _defaultRouter.GetVirtualPath(context);
    }

    // 自定义权限校验方法
    private bool IsAuthorized(ClaimsPrincipal user, string allowedRoles)
    {
        // 你的权限校验逻辑
        if (string.IsNullOrEmpty(allowedRoles)) return true;
        return allowedRoles.Split(',').Any(role => user.IsInRole(role));
    }
}

注意事项

  • 路由顺序:自定义短URL路由必须放在默认路由之前,否则会被默认路由抢先匹配。
  • 性能优化:频繁查询数据库解析路由可能影响性能,建议添加缓存(如MemoryCache)存储短ID与路由映射的关系,定期更新缓存。
  • 异常处理:在RouteAsync中添加异常捕获,避免数据库查询异常导致整个路由系统崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:35:22