4

I've just switched from AttributeRouting to WebApi 2.0 AttributeRouting, and have got a controller and action defined like so:

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

Example query:

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

The response I receive is a 200, with empty content (due to string.Empty).


This all works fine -- but I want to change the email property to be a query parameter instead . So I update the controller to:

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

But now when querying the endpoint with:

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

The response I receive is a 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'"
}

Does anyone know why it doesn't match the route when the parameter is swapped to a query parameter, rather than inline of the url ?


As requested, WebApiConfig is defined like so:

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

    config.MapHttpAttributeRoutes();
}

Thanks !

4

3 回答 3

6

我认为您需要在 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 中评论的答案:路由模板不能以“/”或“~”开头,因此您可以如上所述从路由中删除它

于 2013-11-13T15:15:20.997 回答
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'"
}

具有误导性的是响应消息。

于 2013-11-13T16:29:19.577 回答
2

I think you need to change your Route declaration to this: [Route("~/api/invites?{email}")]

Here is a relevant link: http://attributerouting.net/#route-constraints

于 2013-11-13T14:59:44.797 回答