【问题标题】:WebApi 2.0 Routes not matching with query parameters?WebApi 2.0 路由与查询参数不匹配?
【发布时间】:2013-11-26 05:49:35
【问题描述】:

我刚刚从 AttributeRouting 切换到 WebApi 2.0 AttributeRouting,并且有一个控制器和操作定义如下:

public class InvitesController : ApiController
{
    [Route("~/api/invites/{email}")]
    [HttpGet]
    [ResponseType(typeof(string))]
    public IHttpActionResult InviteByEmail(string email)
    {
        return this.Ok(string.Empty);
    }
}

查询示例:

GET: http://localhost/api/invites/test@foo.com

我收到的响应是 200,内容为空(由于 string.Empty)。


这一切都很好——但我想将电子邮件属性更改为查询参数。所以我将控制器更新为:

public class InvitesController : ApiController
{
    [Route("~/api/invites")]
    [HttpGet]
    [ResponseType(typeof(string))]
    public IHttpActionResult InviteByEmail(string email)
    {
        return this.Ok(string.Empty);
    }
}

但是现在查询端点时:

GET: http://localhost/api/invites?email=test@foo.com

我收到的响应是 404:

{
"message": "No HTTP resource was found that matches the request URI 'http://localhost/api/invites?email=test@foo.com'.",
"messageDetail": "No route providing a controller name was found to match request URI 'http://localhost/api/invites?email=test@foo.com'"
}

有谁知道为什么当参数被交换为查询参数而不是内联url时它与路由不匹配?


根据要求,WebApiConfig 定义如下:

public static void Register(HttpConfiguration config)
{
    var jsonFormatter = config.Formatters.JsonFormatter;
    jsonFormatter.Indent = true;
    jsonFormatter.SerializerSettings.ContractResolver = new RemoveExternalContractResolver();

    config.MapHttpAttributeRoutes();
}

谢谢!

【问题讨论】:

  • 您并没有真正明确您的意图(您正在尝试做什么)您正在使用 POST,您实际上是在请求正文中发布任何信息吗?还是这种方法真的是 GET?
  • 抱歉,当电子邮件通过查询参数传递时,切换到 HttpGet 对 404 没有任何影响。我会更新问题。
  • 我刚刚尝试了您的方案,但无法重现。您能分享一下您的 WebApiConfig.cs 的样子吗?
  • 添加到问题的末尾。
  • 好的 - 我想我明白了。这似乎与我定义的另一条路线发生冲突。如果我将 Route 定义更改为“~/api/invites/create”,并使用 /api/invites/create?email=test@foo.com 调用它,它似乎工作正常。至于它与哪个端点发生冲突,我将不得不更深入地挖掘。那里的响应更清晰一点会很好:(

标签: c# asp.net-web-api asp.net-web-api-routing


【解决方案1】:

我认为您需要将您的 Route 声明更改为:[Route("~/api/invites?{email}")]

这是一个相关链接:http://attributerouting.net/#route-constraints

【讨论】:

  • 这不再使用 3rd Party AttributeRouting 框架(尽管据我了解,它是基于此的)——但我最初确实尝试过,因为它曾经被定义为.现在在 WebApi2.0 AttributeRouting 框架中,尝试在 Route 定义中添加 ? 会引发异常。 System.Web.Http.dll 中发生“System.ArgumentException”类型的异常,但未在用户代码中处理附加信息:路由模板不能以“/”或“~”字符开头,并且不能包含“? '字符。
  • 哦,我的错。我误读了您的问题,看起来@ry8806 知道发生了什么。再次抱歉。
【解决方案2】:

我认为您需要在 Route 中包含查询参数(及其类型),如下所示:

[Route("api/invites/{email:string}")]

使用它将是

POST: http://localhost/api/invites/test@foo.com

或者,如果您想命名查询参数:

[Route("api/invites")]

使用它将是(只要您的方法中有电子邮件参数)

POST: http://localhost/api/invites?email=test@foo.com

正如您在 edhedges 中评论的答案:路由模板不能以“/”或“~”开头,因此您可以像上面那样从路由中删除它

【讨论】:

  • 我可以得到第一个来解决 ([Route("api/invites/{email:string}")]) (有或没有类型)。这是第二个没有([Route(“api/invites”)])的方法,方法中有电子邮件参数。这只是返回初始问题中列出的 404。
  • @Tris 由于 IIS 文件路由,IIS 正在尝试将电子邮件地址中的 .com 与文件匹配。如果没有 IIS 配置更改,您只能在查询字符串中使用电子邮件地址。请参阅stackoverflow.com/a/12847224/324497 以了解在路由中使用电子邮件地址的配置更改。
【解决方案3】:

问题是路由定义的冲突,由于是跨控制器(还有一些路由是“绝对的”(~/))而没有引起注意。下面是一个重现结果的示例。

public class ValuesController : ApiController
{
    [Route("~/api/values")]
    [HttpGet]
    public IHttpActionResult First(string email)
    {
        return this.Ok("first");
    }
}

[RoutePrefix("api/values")]
public class ValuesTwoController : ApiController
{
    [Route("")]
    [HttpGet]
    public IHttpActionResult Second(string email)
    {
        return this.Ok("second");
    }
}

发出请求:

GET: http://localhost/api/values?email=foo

将返回 404 响应:

{
    "message": "No HTTP resource was found that matches the request URI 'http://localhost/api/values?email=foo'.",
    "messageDetail": "No route providing a controller name was found to match request URI 'http://localhost/api/values?email=foo'"
}

误导性的是响应消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2015-11-07
    • 2016-07-03
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    相关资源
    最近更新 更多