因此,我有一个使用默认路由模板{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
答案 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的,与问题无关,这只是我查找数据库记录的方式。