【问题标题】:struggling with an ASP.NET MVC5 routing issue努力解决 ASP.NET MVC5 路由问题
【发布时间】:2018-07-10 12:36:29
【问题描述】:

所以,我有一个使用默认路由模板 {controller}/{action}/{id} 的 MVC5 站点,它工作正常。站点中的大多数内容都需要登录(即几乎所有地方都使用 [Authorize] 属性),这很好用。

好吧,现在我需要在使用某种链接模式时允许匿名访问选择页面:App/{token}/{action}。 {token} 是一个随机字符串,与我的数据库中的某些内容相关联。我可以随意发行和停用这些令牌。

我通过实现自定义 RouteBase 来解析这些令牌的传入 URL,并且至关重要的是,将令牌值添加到 RouteData.DataTokens 中,从而使这个新的 App/{token}/{action} 路由工作我的App 控制器可以使用它而无需明确的操作参数。因此,我将这条新路由添加到默认路由的 ahead 路由表中,如下所示:

// new route here
routes.Add("AppToken", new AnonAppAccessRoute());           

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

这是问题/问题:添加此 now 路由现在使我的默认路由停止工作 - 现在一切都通过 AnonAppAccessRoute 进行,这当然只适用于少数几件事。我不明白如何让我的AnonAppAccessRoute 仅适用于具有特定模式的 URL。 MapRoute 方法接受 URL 模式,但 Add 路由似乎不允许您对其进行过滤。我错过了什么?我已经浏览了很多关于路由的博客和文档,但是我没有找到关于使用 DataTokens 集合的好信息(我觉得这对我的方法很重要),而且我没有看到很好的解释Add显式路由与调用MapRoute之间的区别。

这是我自定义RouteBase的代码:

public class AnonAppAccessRoute : RouteBase
{
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;

        string[] pathElements = httpContext.Request.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
        if (pathElements.Length > 0)
        {
            string token = TryGetArrayElement(pathElements, 1);
            if (!string.IsNullOrEmpty(token))
            {
                result = new RouteData(this, new MvcRouteHandler());
                result.DataTokens.Add("appToken", token);
                result.Values.Add("controller", "App");
                result.Values.Add("action", TryGetArrayElement(pathElements, 2, "Index"));
            }
        }

        return result;
    }

    private string TryGetArrayElement(string[] array, int index, string defaultValue = null)
    {
        try
        {
            return array[index];
        }
        catch
        {
            return defaultValue;
        }
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return null;
    }
}

【问题讨论】:

    标签: asp.net-mvc-5


    【解决方案1】:

    我通过删除自定义 RouteBase 来实现这一点,而是像这样使用这个 MapRoute 调用:

    routes.MapRoute(
        name: "AppAnon",
        url: "App/{token}/{action}",
        defaults: new { controller = "App", action = "Index" }
    );
    

    然后,在我的 App 控制器中,我在 Initialize 覆盖中执行了此操作:

    protected AppToken _appToken = null;
    
    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);
        string token = requestContext.RouteData.Values["token"]?.ToString();
        _appToken = Db.FindWhere<AppToken>("[Token]=@token", new { token });
        if (!_appToken?.IsActive ?? false) throw new Exception("The token is not found or inactive.");
    }
    

    这样,我的“令牌”可通过_appToken 变量用于所有控制器操作,并且已经过验证。我不需要使用RouteData.DataTokens。请注意,我的 Db.FindWhere 语句是特定于 ORM 的,与问题没有真正的关系——这只是我查找数据库记录的方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 2014-11-01
      相关资源
      最近更新 更多