当没有找到Action时,重复的路由需要回退到下一个匹配的路由

时间:2012-12-14 09:40:02

标签: asp.net routing webforms asp.net-web-api asp.net-routing

我有一种情况需要覆盖ASP.NET WebForms应用程序中旧的HttpHandler API中的方法。我正在使用WebAPI作为新API的基础,除了在新API中找不到操作时我需要回退路由,它一直很好用。目前情况并非如此,只要WebAPI控制器没有匹配的操作,我就会得到“404:Not Found”。

我对新API的路由如下:

var apiroute = routes.MapHttpRoute(
    "API Default",
    "api/{language}-{country}/{controller}/{action}/{id}",
    new { id = RouteParameter.Optional }
);

旧的Httphandler API按如下方式注册其路由(顺序在WebAPI路由之后):

var route = new Route("api/{language}-{country}/Person/{command}", this);
RouteTable.Routes.Add(route);

我想/ api / en-US / Person / List匹配第一条路线,如果一个PersonController有一个List动作,但如果没有则回退到旧api。

问题:是否可以在第一条路线上添加过滤器,只有在操作系统确实可用的情况下才匹配?我怎么能做到这一点?

1 个答案:

答案 0 :(得分:1)

<强>更新

您可能还想调查attribute based routing这可能是一个更简洁的解决方案,只有您使用路由属性进行注释的操作才会与路线匹配,这可能有助于您实现所需目标。

虽然可能有更好的方法,但如果您实施自定义IRouteConstraintthis article

您可以改进的高度粗略和准备好的方法如下:

public class IfActionExistsConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var actionName = values["Action"] as string;

        if (actionName == null)
        {
            return false;
        }

        var controllerName = values["Controller"] as string;
        var controllerTypeResolver = GlobalConfiguration.Configuration.Services.GetHttpControllerTypeResolver();
        var controllerTypes = controllerTypeResolver.GetControllerTypes(GlobalConfiguration.Configuration.Services.GetAssembliesResolver());
        var controllerType = controllerTypes.SingleOrDefault(ct => ct.Name == string.Format("{0}Controller", controllerName));

        if(controllerType == null)
        {
            return false;
        }

        return controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null;
    }
}

<强>注册

var apiroute = routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{language}-{country}/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: new { IfActionExistsConstraint = new IfActionExistsConstraint() }
);