Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 2 使用动态前缀改变MVC路由,同时保持向后url兼容性_Asp.net Mvc 2_Asp.net Mvc Routing - Fatal编程技术网

Asp.net mvc 2 使用动态前缀改变MVC路由,同时保持向后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

事实并非如此,我有一个网站,你必须在一个单一的url和一个cookie设置跟踪哪个客户你是附属。我想更改此设置,以便某些控制器仅使用如下url:

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运算符。