【问题标题】:WebApi Controller with two GET actions具有两个 GET 操作的 WebApi 控制器
【发布时间】:2013-03-18 20:39:51
【问题描述】:

我想要两个不同的 GET 操作来查询数据,名称和 ID,

我有这些路线:

        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "ActionApiByName",
            routeTemplate: "api/{controller}/{action}/{name}",
            defaults: new { name = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

以及控制器中的这些操作:

    [HttpGet]
    public CompanyModel CompanyId(Guid id)
    {
          //Do something
    }


    [HttpGet]
    public CompanyModel CompanyName(string name)
    {
            //Do something
    }

当像这样的调用:http://localhost:51119/api/companies/CompanyId/3cd97fbc-524e-47cd-836c-d709e94c5e1e 工作并获得 'CompanyId' 方法时,

http://localhost:51119/api/companies/CompanyName/something 的类似调用让我发现 404 未找到

但是这个: 'http://localhost:51119/api/companies/CompanyName/?name=something' 工作正常

谁能解释这种行为以及我做错了什么?

【问题讨论】:

    标签: c# asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    Web API 路由选择器无法知道 URL 末尾的字符串是否为 GUID。因此,它不会为适当的 GET 操作选择正确的路由。

    为了选择正确的路由,需要为 GUID uri 模板添加路由约束。

        public class GuidConstraint : IHttpRouteConstraint
        {
            public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
                              HttpRouteDirection routeDirection)
            {
                if (values.ContainsKey(parameterName))
                {
                    string stringValue = values[parameterName] as string;
    
                    if (!string.IsNullOrEmpty(stringValue))
                    {
                        Guid guidValue;
    
                        return Guid.TryParse(stringValue, out guidValue) && (guidValue != Guid.Empty);
                    }
                }
    
                return false;
            }
        }
    

    然后,将约束添加到将处理 GUID 的路由。

    config.Routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional },
                constraints: new { id = new GuidConstraint() }  // Added
            );
    

    由于此路由比一般的“字符串”路由更具体,因此需要将其放在要解析名称的路由之上。

    这应该适当地路由到操作。

    希望这会有所帮助。

    【讨论】:

    • 我接受你的回答,因为这很好用,但我仍然不明白为什么它没有映射到正确的操作,在我指示的 URI 中,一次是“CompanyName”,一次是“CompanyId” ,是不是应该选择合适的动作?
    • This SO question 可能有助于解释原因。默认情况下,Web API 路由遵循 REST 约定。因此,您可能会看到与普通 MVC 路由不同的行为。
    • 太棒了! Web API 是经过深思熟虑的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 2014-09-29
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多