Asp.net mvc 2 使用动态前缀改变MVC路由,同时保持向后url兼容性
事实并非如此,我有一个网站,你必须在一个单一的url和一个cookie设置跟踪哪个客户你是附属。我想更改此设置,以便某些控制器仅使用如下url:Asp.net mvc 2 使用动态前缀改变MVC路由,同时保持向后url兼容性,asp.net-mvc-2,asp.net-mvc-routing,Asp.net Mvc 2,Asp.net Mvc Routing,事实并非如此,我有一个网站,你必须在一个单一的url和一个cookie设置跟踪哪个客户你是附属。我想更改此设置,以便某些控制器仅使用如下url: using System; using System.Web; using System.Web.Routing; namespace Examples.Extensions { public class MustBeFriendlyName : IRouteConstraint { public bool Match
using System;
using System.Web;
using System.Web.Routing;
namespace Examples.Extensions
{
public class MustBeFriendlyName : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this is a valid friendlyName
// MUST BE CERTAIN friendlyName DOES NOT MATCH ANY
// CONTROLLER NAMES OR AREA NAMES
var _db = new DbContext();
return _db.FriendlyNames.FirstOrDefault(x => x.FriendlyName.ToLowerInvariant() ==
values[parameterName].ToString().ToLowerInvariant()) != null;
}
}
public class MustNotRequireFriendlyName : IRouteConstraint
{
private const string controllersRequiringFriendlyNames =
"SignIn~SignOut~Account";
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this controller does NOT require a friendlyName
return controllersRequiringFriendlyNames.ToLowerInvariant()
.Contains(values[parameterName].ToString().ToLowerInvariant());
}
}
}
/{friendlyName}/{controller}/{index}/{id}
这个友好的名称是唯一的,让我可以选择正确的客户,而无需使用cookie kludge
我有一些控制器:主页
,重定向
,我不想要友好名称的一部分(可能更多)
我还有一些其他人符合这一类别,我想进入他们自己的领域。我怎么能不将这些区域作为有效的友好名称包括在内?例如,我有一个控制器,为iframe中名为Framed
的内容提供服务。目前,这个url看起来像/Framed/action/id。我可以将它放在一个名为Framed
的区域中,控制器的名称与操作相同,我应该仍然能够维护相同的url
对于控制器错误
我希望友好名称是可选的
我还需要其他控制器的友好名称:登录
,注销
,帐户
一旦我有了路由,问题是修改代码,使我的重定向保持friendlyurl。有什么办法吗
我的问题是提出一个好的攻击计划,如何改变我的网站的路由。我必须保持一些url的向后兼容性,也就是说,任何我不想要的友好url部分,包括我讨论过的分割到它们自己区域的控制器。我正在寻找任何关于如何安排这一点并着手更改更改的好建议。要实现您的目标,您需要将路由和
路由约束相结合。此外,您还需要强制执行规则,确保friendlyName
是唯一的,并且不同于任何控制器或区域的名称
在Global.asax.cs中的RegisterRoutes()
中,以下路径应足够:
routes.MapRoute(
"WithFriendlyName",
"{friendlyName}/{controller}/{index}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { friendlyName = new MustBeFriendlyName() }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = new MustNotRequireFriendlyName() }
);
RouteConstraint应该如下所示:
using System;
using System.Web;
using System.Web.Routing;
namespace Examples.Extensions
{
public class MustBeFriendlyName : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this is a valid friendlyName
// MUST BE CERTAIN friendlyName DOES NOT MATCH ANY
// CONTROLLER NAMES OR AREA NAMES
var _db = new DbContext();
return _db.FriendlyNames.FirstOrDefault(x => x.FriendlyName.ToLowerInvariant() ==
values[parameterName].ToString().ToLowerInvariant()) != null;
}
}
public class MustNotRequireFriendlyName : IRouteConstraint
{
private const string controllersRequiringFriendlyNames =
"SignIn~SignOut~Account";
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this controller does NOT require a friendlyName
return controllersRequiringFriendlyNames.ToLowerInvariant()
.Contains(values[parameterName].ToString().ToLowerInvariant());
}
}
}
这应该让你开始
就重定向生成的URL而言,如果路由设置正确,则应随后生成URL,以便您可能需要的唯一更改是确保传递{friendlyName}
在进一步进行更改时,您可能需要添加一些额外的路由和约束。要实现您的目标,您需要路由和路由约束的组合。此外,您还需要强制执行规则,确保friendlyName
是唯一的,并且不同于任何控制器或区域的名称
在Global.asax.cs中的RegisterRoutes()
中,以下路径应足够:
routes.MapRoute(
"WithFriendlyName",
"{friendlyName}/{controller}/{index}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { friendlyName = new MustBeFriendlyName() }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = new MustNotRequireFriendlyName() }
);
RouteConstraint应该如下所示:
using System;
using System.Web;
using System.Web.Routing;
namespace Examples.Extensions
{
public class MustBeFriendlyName : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this is a valid friendlyName
// MUST BE CERTAIN friendlyName DOES NOT MATCH ANY
// CONTROLLER NAMES OR AREA NAMES
var _db = new DbContext();
return _db.FriendlyNames.FirstOrDefault(x => x.FriendlyName.ToLowerInvariant() ==
values[parameterName].ToString().ToLowerInvariant()) != null;
}
}
public class MustNotRequireFriendlyName : IRouteConstraint
{
private const string controllersRequiringFriendlyNames =
"SignIn~SignOut~Account";
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// return true if this controller does NOT require a friendlyName
return controllersRequiringFriendlyNames.ToLowerInvariant()
.Contains(values[parameterName].ToString().ToLowerInvariant());
}
}
}
这应该让你开始
就重定向生成的URL而言,如果路由设置正确,则应随后生成URL,以便您可能需要的唯一更改是确保传递{friendlyName}
随着更改的深入,您可能需要添加一些额外的路由和约束。只是想添加一些,因为可选前缀在过去几天一直困扰着我。虽然我想使用@CouncellorBen提供的解决方案,但我还需要能够以相同的名称对路由进行寻址,这在使用2条路由时是不可能的
我花了一些时间才找到答案,但最终的解决办法似乎非常简单。我只需要创建一个中间聚合路由:
public class AggregateRoute : RouteBase
{
private readonly RouteBase[] _routes;
public AggregateRoute(params RouteBase[] routes)
{
_routes = routes;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData routeData = null;
foreach (var route in _routes)
{
routeData = route.GetRouteData(httpContext);
if (routeData != null) break;
}
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
VirtualPathData virtualPath = null;
foreach (var route in _routes)
{
virtualPath = route.GetVirtualPath(requestContext, values);
if (virtualPath != null) break;
}
return virtualPath;
}
}
这使我能够做到:
routes.Add(
"RouteName",
new AggregateRoute(
new Route("{path}", new MvcRouteHandler()),
new Route("{prefix}/{path}", new MvcRouteHandler())
)
);
它允许以相同的名称解析任一路由,这在单独添加两个路由时是不可能的:
Url.RouteLink("RouteName", new RouteValueDictionary{
new{path="some-path"}});
Url.RouteLink("RouteName", new RouteValueDictionary{
new{path="some-prefix/some-path"}});
只是想补充一下,因为可选前缀在过去几天一直在咬我。虽然我想使用@CouncellorBen提供的解决方案,但我还需要能够以相同的名称对路由进行寻址,这在使用2条路由时是不可能的
我花了一些时间才找到答案,但最终的解决办法似乎非常简单。我只需要创建一个中间聚合路由:
public class AggregateRoute : RouteBase
{
private readonly RouteBase[] _routes;
public AggregateRoute(params RouteBase[] routes)
{
_routes = routes;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData routeData = null;
foreach (var route in _routes)
{
routeData = route.GetRouteData(httpContext);
if (routeData != null) break;
}
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
VirtualPathData virtualPath = null;
foreach (var route in _routes)
{
virtualPath = route.GetVirtualPath(requestContext, values);
if (virtualPath != null) break;
}
return virtualPath;
}
}
这使我能够做到:
routes.Add(
"RouteName",
new AggregateRoute(
new Route("{path}", new MvcRouteHandler()),
new Route("{prefix}/{path}", new MvcRouteHandler())
)
);
它允许以相同的名称解析任一路由,这在单独添加两个路由时是不可能的:
Url.RouteLink("RouteName", new RouteValueDictionary{
new{path="some-path"}});
Url.RouteLink("RouteName", new RouteValueDictionary{
new{path="some-prefix/some-path"}});
我想我在尝试实现代码时发现了一些拼写错误。你有“{friendlyName}/{controller}/{index}/{id}”
而不是“{friendlyName}/{controller}/{action}/{id}”
,在的mustnotrequireRefriendlyname
中,如果你的评论是正确的,那么这个语句就需要一个not操作符。我想我在你的代码中发现了一些打字错误,因为我正在尝试实现它。您有“{friendlyName}/{controller}/{index}/{id}”
而不是“{friendlyName}/{controller}/{action}/{id}”
并且在mustnotrequirementlyname
中,如果您的注释正确,则该语句需要not运算符。