路由错误访问操作

时间:2015-07-14 17:05:37

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

默认情况下,MVC中的网址路由是 {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 时,它将转到详细信息操作。它不会转到类别控制器中的创建操作。

我怎样才能解决这个问题?

3 个答案:

答案 0 :(得分:4)

两种方式:

使用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 });

答案 1 :(得分:2)

虽然上面的答案是正确的,但这是一个更简单的解决方案,但如果您按照Dave的回答将操作添加到控制器,它将无法动态更新。

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

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

activated drawables

在此示例中,只有当网址不是routes.MapRoute( name: "CategoryDetails", url: "Category/{key}", defaults: new { controller = "Category", action = "Details" }, constraints: new { key = @"[^create|update|delete]" } ); CategoryDetailsCategory/create时,Category/update路由才会匹配。例如,广告/汽车将匹配并使用Category/delete操作。

答案 2 :(得分:0)

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

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

  • items / - for elements of elements
  • items / {name_or_id} / details - 显示元素的详细信息
  • items / {name_or_id} / edit - 更新元素
  • items / create - tu创建一个新元素

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

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