【问题标题】:Routing wrong access the action路由错误访问动作
【发布时间】:2015-07-14 17:05:36
【问题描述】:

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

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

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

因此它将显示页面中的所有类别。

然后我注册另一个名为 CategoryDe​​tails 的地图路线

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

当有人访问 mydomain.com/category/cars 时,它会显示所有与汽车相关的产品。

同一控制器还具有其他操作,例如创建、编辑、删除等

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

我该如何解决这个问题?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-routing


    【解决方案1】:

    两种方式:

    使用Route Constraint 确保 {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/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 });
    

    【讨论】:

    • 似乎第二种解决方案是直接的方式,但第一种解决方案对性能有影响吗?
    • 如果您使用已知类别的缓存字典查找来匹配 - 通常没问题。我使用这种方法,它是亚毫秒
    【解决方案2】:

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

    据我了解,如果 {key} 是现有操作,您希望它由默认路由处理,而不是使用 Category 控制器上的 Details 操作。

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

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

    在此示例中,CategoryDetails 路由仅在 url 不是 Category/createCategory/updateCategory/delete 时匹配。例如,广告/汽车将匹配并使用 Details 操作。

    【讨论】:

    • 你的代码不是在做相反的事情吗?不是说CategoryDe​​tails只有在key is create、update或者delete的时候才会匹配?
    • 我想你错过了动作名称中的 [ ]?我试过放那个符号,现在它正在工作......
    • 嗯..我认为它仍然是错误的。例如 car 将不匹配您的正则表达式。我不确定是否可以做你想做的事。在这里查看:regexr.com/3bctm
    • 哇,从来没有想过要这样做——很棒的东西
    【解决方案3】:

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

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

    • items/ - 元素列表
    • items/{name_or_id}/details - 显示元素的详细信息
    • items/{name_or_id}/edit - 更新元素
    • items/create - 你创建一个新元素

    对于您的情况,它可以是:

            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" });
    

    【讨论】:

      猜你喜欢
      • 2019-04-15
      • 1970-01-01
      • 2017-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多