好吧,你并没有真正定义什么是“错误”路由,所以这是我的定义:
- 控制器或动作在项目中不存在。
- 如果传递了“id”,则它必须存在于操作方法中。
路线
我使用约束来做到这一点。 AFAIK,不可能对可选参数使用约束。这意味着为了使id 参数可选,您需要3 个路由。
routes.MapRoute(
name: "DefaultWithID",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { action = new ActionExistsConstraint(), id = new ParameterExistsConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { action = new ActionExistsConstraint() }
);
routes.MapRoute(
name: "Second",
url: "{*catchall}",
defaults: new { controller = "Home", action = "Index" }
);
ActionExistsConstraint
public class ActionExistsConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest)
{
var action = values["action"] as string;
var controller = values["controller"] as string;
var thisAssembly = this.GetType().Assembly;
Type[] types = thisAssembly.GetTypes();
Type type = types.Where(t => t.Name == (controller + "Controller")).SingleOrDefault();
// Ensure the action method exists
return type != null && type.GetMethod(action) != null;
}
return true;
}
}
ParameterExistsConstraint
public class ParameterExistsConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest)
{
var action = values["action"] as string;
var controller = values["controller"] as string;
var thisAssembly = this.GetType().Assembly;
Type[] types = thisAssembly.GetTypes();
Type type = types.Where(t => t.Name == (controller + "Controller")).SingleOrDefault();
var method = type.GetMethod(action);
if (type != null && method != null)
{
// Ensure the parameter exists on the action method
var param = method.GetParameters().Where(p => p.Name == parameterName).FirstOrDefault();
return param != null;
}
return false;
}
return true;
}
}