WebApi 2.0 Routes not matching with query parameters?

廉价感情. 提交于 2019-12-19 03:45:38

问题


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 !


回答1:


I think you need to include the query parameter (along with its type) in the Route as follows:

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

using it will be

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

Alternatively if you want to name the query parameter:

[Route("api/invites")]

using it will be (as long as you have an email parameter in your method)

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

As you comment in edhedges answer: the route template cannot start with a '/' or a '~', so you can remove that from the route as above




回答2:


Issue is a clash of route definitions, which went unnoticed due to being cross-controller (and also some of the routes being 'absolute' (~/)). Below is an example that reproduces the result.

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");
    }
}

Issuing a request:

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

Will return a 404 with a response of:

{
    "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'"
}

What is misleading is the response message.




回答3:


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



来源:https://stackoverflow.com/questions/19956974/webapi-2-0-routes-not-matching-with-query-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!