C# 路由错误访问操作

C# 路由错误访问操作,c#,asp.net-mvc,asp.net-mvc-routing,C#,Asp.net Mvc,Asp.net Mvc Routing,默认情况下,MVC中的URL路由为{controller}/{action}/{id}。然后我们可以访问mydomain.com/Products/Details/1等 现在,我已经注册了另一条名为CategoryLandingPage的地图路线 routes.MapRoute( name: "CategoryLandingPage", url: "category", defaults: new { controller = "Category", action = "Index" });

默认情况下,MVC中的URL路由为{controller}/{action}/{id}。然后我们可以访问mydomain.com/Products/Details/1等

现在,我已经注册了另一条名为CategoryLandingPage的地图路线

routes.MapRoute(
name: "CategoryLandingPage",
url: "category",
defaults: new { controller = "Category", action = "Index" }); 
因此,它将显示页面中的所有类别

然后我注册了另一个叫做CategoryDetails的地图路线

routes.MapRoute(
name: "CategoryDetails", 
url: "category/{categoryName}", 
defaults: new { controller = "Category", action = "Details", categoryName = UrlParameter.Optional });
当有人访问mydomain.com/category/cars时,它将显示与汽车相关的所有产品

同一控制器还具有另一个操作,如创建、编辑、删除和更多操作

问题是,当我访问mydomain.com/category/create时,它将转到详细操作。它不会转到类别控制器中的创建操作

我怎样才能解决这件事?

有两种方法:

使用确保{categoryName}部分与您的类别之一匹配:

//You will have to make this
var categoryRouteConstraint = new CategoryRouteConstraint();

routes.MapRoute(
name: "CategoryDetails", 
url: "category/{categoryName}", 
constraints: new { categoryName = categoryRouteConstraint }
defaults: new { controller = "Category", action = "Details", categoryName = UrlParameter.Optional });
路由约束示例:

public class CategoryRouteConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (routeDirection == RouteDirection.UrlGeneration)
                return true;

            if (string.Equals(parameterName, "categoryName", StringComparison.OrdinalIgnoreCase))
            {
                //return true if (string)values[parameterName] == "known category name"
            }

            return false;
        }
    }
routes.MapRoute(
    name: "CategoryDetails",
    url: "Category/{key}",
    defaults: new { controller = "Category", action = "Details" },
    constraints: new { key = @"[^create|update|delete]" }
);
或者,首先拦截特定操作:

routes.MapRoute(
name: "CategoryDetails", 
url: "category/create", 
defaults: new { controller = "Category", action = "Create", categoryName = UrlParameter.Optional });

routes.MapRoute(
name: "CategoryDetails", 
url: "category/delete", 
defaults: new { controller = "Category", action = "Delete", categoryName = UrlParameter.Optional });

//Do one for Edit, Delete

//CategoryDetails route after
routes.MapRoute(
name: "CategoryDetails", 
url: "category/{categoryName}", 
defaults: new { controller = "Category", action = "Details", categoryName = UrlParameter.Optional });

你不能这样做。您通过url覆盖了默认路由:“category/{categoryName}”

解决路由问题的好方法是将其命名如下:

  • 项目/-用于元素列表
  • items/{name\u或\u id}/details-显示元素的详细信息
  • items/{name\u或\u id}/edit-更新元素
  • 项目/创建-创建新元素
对于您的情况,它可以是:

        routes.MapRoute(
            name: "CategoryLandingPage",
            url: "categories",
            defaults: new { controller = "Category", action = "Index" });

        routes.MapRoute(
            name: "CategoryDetails",
            url: "categories/{categoryName}/details",
            defaults: new { controller = "Category", action = "Details" });

        routes.MapRoute(
            name: "CategoryUpdate",
            url: "categories/{categoryName}/edit",
            defaults: new { controller = "Category", action = "Edit" });

        routes.MapRoute(
            name: "CategoryLandingPage",
            url: "categories/create",
            defaults: new { controller = "Category", action = "Create" });

虽然上面的答案是正确的,但这是一个更简单的解决方案,尽管如果您像Dave的答案那样向控制器添加操作,它不会动态更新

据我所知,如果{key}是一个现有的操作,那么您希望它由默认路由处理,而不是使用Category控制器上的Details操作

为了实现这一点,您可以在关键约束中列出所有可能的操作:

public class CategoryRouteConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (routeDirection == RouteDirection.UrlGeneration)
                return true;

            if (string.Equals(parameterName, "categoryName", StringComparison.OrdinalIgnoreCase))
            {
                //return true if (string)values[parameterName] == "known category name"
            }

            return false;
        }
    }
routes.MapRoute(
    name: "CategoryDetails",
    url: "Category/{key}",
    defaults: new { controller = "Category", action = "Details" },
    constraints: new { key = @"[^create|update|delete]" }
);

在此示例中,
categorydeails
路由仅在url不是
Category/create
Category/update
Category/delete
时匹配。例如,广告/汽车将匹配并使用
详细信息
操作。

似乎第二种解决方案是直接的方法,但对于第一种解决方案,对性能有任何影响吗?如果使用已知类别的缓存字典查找进行匹配,通常可以。我使用这种方法,它是次毫秒级的,您的代码不是在做相反的事情吗?这不是说CategoryDetails只有在键为create、update或delete时才会匹配吗?我想您在actions名称中遗漏了[]?我试着把那个符号放进去,现在它起作用了……嗯。。我认为这仍然是错误的。例如,
car
将与您的正则表达式不匹配。我不确定是否有可能做你想做的事。看看这里:哇,从来没有想过要这样做-很棒的东西