使用ASP.NET WebApi,如何使路由排除一组控制器

本文关键字:控制器 一组 排除 路由 NET ASP WebApi 何使 使用 | 更新日期: 2023-09-27 18:26:56

我已经创建了两个用于导出类型模式和wadl的控制器,其他一切都是api 的一部分

所以我创建了三条路线,两条用于特殊控制器(Schema和Wadl),一条用于"其他一切":

        config.Routes.MapHttpRoute(
            name: "Schemas",
            routeTemplate: "api/{controller}/{typeName}/{subType}",
            defaults: new { subtype = RouteParameter.Optional },
            constraints: new { controller = @"Schemas" }
        );
        config.Routes.MapHttpRoute(
            name: "Wadl",
            routeTemplate: "api/{controller}",
            defaults: null,
            constraints: new { controller = @"Wadl" }
        );
        config.Routes.MapHttpRoute(
            name: "api",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: somethingsomethingsomething }
        );

我尝试关注此页面:http://stephenwalther.com/archive/2008/08/07/asp-net-mvc-tip-30-create-custom-route-constraints

并在他们的NotEquals类上创建了一个变体:

public class NotEqual : IRouteConstraint
{
    private IEnumerable<string> Matches;
    public NotEqual(IEnumerable<string> matches)
    {
        Matches = matches;
    }
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        bool output = true;
        var name = values[parameterName].ToString();
        foreach (var match in Matches)
        {
            if (name.Contains(match))
            {
                output = false;
                break;
            }
        }
        return output;
    }
}

并将第三条路线更改为:

        config.Routes.MapHttpRoute(
            name: "api",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { controller = new NotEqual(new List<string> { "Schemas", "Wadl" }) }
        );
public class NotEqual : IRouteConstraint
{
    private IEnumerable<string> Matches;
    public NotEqual(IEnumerable<string> matches)
    {
        Matches = matches;
    }
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        bool output = true;
        var name = values[parameterName].ToString();
        foreach (var match in Matches)
        {
            if (name.Contains(match))
            {
                output = false;
                break;
            }
        }
        return output;
    }
}

不起作用,它仍然适用于所有三个控制器

它只需一条路线就可以正常工作,但自动帮助页面很难看,而且会误导人。

如果我在Match上设置一个断点,它就不会到达断点。

Regex约束非常有效,只是"其他一切"约束不起作用

为什么不起作用?

使用ASP.NET WebApi,如何使路由排除一组控制器

以下是我自己的其他答案组合:

在Register()中有以下内容:

        config.Routes.MapHttpRoute(
            name: "default",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { controller = @"^(?:(?!Wadl|Schemas).)*$" }
        );
        config.MapHttpAttributeRoutes();
        <snip>
        config.EnsureInitialized();

这为您提供了控制器的默认路由,您可以通过在上面的regex中添加更多的|语句来排除它们。

然后,为了在不必担心优先级的情况下进行自定义路由,标记您的操作如下:

    [Route("schemas/{typeName}")]
    public XmlSchema GetSchema(string typeName) {}
    [Route("schemas/{typeName}/{subType}")]
    public XmlSchema GetSchema(string typeName, int subType)

这些控制器中未标记的方法将没有到它们的路由,就像它们是私有的一样。

    public string Test(int id)

老实说,如果可以的话,你应该使用AttributeRouting——它在代码中更清晰,对于新加入项目的人来说,更容易看到什么路线正在达到什么目的。

http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

第二个路由比上一个路由更通用,因为它在id匹配的路由之前注册。只需将第二个移动到底部并构建应用程序,它就可以工作了。至于约束,你可以使用类似new {id = @"'d+" }的东西,但只有当你在url中使用相同的格式和不同类型的数据时,这才有效,例如api/myController/123,api/myCntroller/my Name。等等