路由错误访问动作
Routing wrong access the action
默认情况下,URL MVC 中的路由是 {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 时,它将转到 详细信息操作 。它不会转到类别控制器中的创建操作。
我该如何解决这个问题?
两种方式:
要么使用 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 });
你不能这样。您通过 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" });
虽然上面的答案是正确的,但这是一个更简单的解决方案,尽管如果您将操作添加到控制器,它不会像 Dave 的答案那样动态更新。
据我了解,如果 {key} 是现有操作,您希望它由默认路由处理,而不是使用类别控制器上的详细信息操作。
为了实现这一点,您可以在关键约束中列出所有可能的操作:
routes.MapRoute(
name: "CategoryDetails",
url: "Category/{key}",
defaults: new { controller = "Category", action = "Details" },
constraints: new { key = @"[^create|update|delete]" }
);
在此示例中,仅当 url 不是 Category/create
或 Category/update
或 Category/delete
时,CategoryDetails
路由才会匹配。例如 ads/cars 将匹配并使用 Details
操作。
默认情况下,URL MVC 中的路由是 {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 时,它将转到 详细信息操作 。它不会转到类别控制器中的创建操作。
我该如何解决这个问题?
两种方式:
要么使用 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 });
你不能这样。您通过 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" });
虽然上面的答案是正确的,但这是一个更简单的解决方案,尽管如果您将操作添加到控制器,它不会像 Dave 的答案那样动态更新。
据我了解,如果 {key} 是现有操作,您希望它由默认路由处理,而不是使用类别控制器上的详细信息操作。
为了实现这一点,您可以在关键约束中列出所有可能的操作:
routes.MapRoute(
name: "CategoryDetails",
url: "Category/{key}",
defaults: new { controller = "Category", action = "Details" },
constraints: new { key = @"[^create|update|delete]" }
);
在此示例中,仅当 url 不是 Category/create
或 Category/update
或 Category/delete
时,CategoryDetails
路由才会匹配。例如 ads/cars 将匹配并使用 Details
操作。