2

我有一种情况,我需要在 ASP.NET WebForms 应用程序中覆盖旧 HttpHandler API 中的方法。我使用 WebAPI 作为新 API 的基础,它运行良好,除了在新 API 中找不到操作时我需要路由回退。目前这不是真的,相反,只要 WebAPI 控制器没有匹配的操作,我就会得到“404:未找到”。

我对新 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);

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

问题:是否可以将过滤器添加到第一个路由以仅在控制器上确实可用操作时才匹配?我还能怎么做到这一点?

4

1 回答 1

1

更新

您可能还想研究基于属性的路由,这可能是一个更简洁的解决方案,只有您使用路由属性注释的操作才会与路由匹配,这可能会帮助您实现您想要的。

或者

尽管可能有比这更好的方法,但如果您实现自定义,IRouteConstraint例如this 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() }
);
于 2012-12-14T11:08:10.533 回答