苦苦应对ASP.NET MVC5路由问题

时间:2018-07-10 12:36:29

标签: asp.net-mvc-5

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

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

我通过实现自定义RouteBase来解析新的App / {token} / {action}路由,该自定义App解析这些令牌的传入URL,并且至关重要的是,将令牌值添加到RouteData.DataTokens这样我的// 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 } ); 控制器就可以使用它,而无需显式的动作参数。因此,我将此新路由添加至默认路由的路由表 中,如下所示:

AnonAppAccessRoute

这是问题所在:现在添加此路由已使我的默认路由停止工作-一切现在都在AnonAppAccessRoute中进行,这当然仅适用于某些情况。我不了解如何使我的MapRoute仅适用于具有特定模式的网址。 Add方法接受URL模式,但是Add路由似乎无法让您对其进行过滤。我想念什么?我到处浏览了很多有关路由的博客和文档,但是我没有找到有关使用DataTokens集合的好信息(我认为这对我的方法很重要),而且我也没有看到关于它的很好的解释。 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; } } 的代码:

_.pick

1 个答案:

答案 0 :(得分:0)

我通过删除自定义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的,与问题无关,这只是我查找数据库记录的方式。