4
votes

On my Web API I have a Document Controller with two simple actions:

[AllowAnonymous]
public class DocumentController : ApiController
{    
    public String Get(int id)
    {
        return "test";
    }

    public String Get(string name)
    {
        return "test2";
    }
}

The following URL (executes the first function) works fine:

http://localhost:1895/API/Document/5

But this URL (should execute the second function):

http://localhost:1895/API/Document/test

Throws this error:

{ "message": "The request is invalid.", "messageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'xx.yy.Document Get(Int32)' in 'API.Controllers.DocumentController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter." }

This is the MapHttpRoute in the WebApiConfig:

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

What am I doing wrong? Please advise.

1

1 Answers

2
votes

Your second function has a parameter name, and the default parameter is called id. With your current setup, you can access the second function on

http://localhost:1895/API/Document/?name=test

To make the URLs work as you have specified previously, I would suggest using attribute routing and route constraints.

Enable attribute routing:

config.MapHttpAttributeRoutes();

Define routes on your methods:

[RoutePrefix("api/Document")]
public class DocumentController : ApiController
{    
    [Route("{id:int}")]
    [HttpGet]
    public String GetById(int id)   // The name of this function can be anything now
    {
        return "test";
    }

    [Route("{name}"]
    [HttpGet]
    public String GetByName(string name)
    {
        return "test2";
    }
}

In this example, GetById has a constraint on the route ({id:int}) which specifies that the parameter must be an integer. GetByName has no such constraint so should match when the parameter is NOT an integer.