Search code examples
c#asp.net-web-apiasp.net-web-api-routingattributerouting

Multiple GET's in Web API calling wrong action


I have a Web API, that looks like the following...

public class LeaguesController : ApiController
{
    //api/Leagues/active/1
    //api/Leagues/complete/1
    //api/Leagues/both/1
    [GET("api/Leagues/{type}/{id}")]
    public List<Competition> Get([FromUri]int id, 
                                [FromUri]CompetitionManager.MiniLeagueType type)
    {
        return CompetitionManager.GetUsersMiniLeagues(id, true, type);
    }

    //api/Leagues/GetMiniLeagueTable/3
    [GET("api/Leagues/GetMiniLeagueTable/{id}")]
    public List<SportTableRow> GetMiniLeagueTable([FromUri]int id)
    {
        return SportManager.GetMiniLeagueTable("", id).TableRows;
    }
}

When I call the first method Get, this works fine. When I use fiddler or Chrome REST Client to call the second method GetMiniLeagueTable, I am getting the following error:

{ Message: "The request is invalid." MessageDetail: "The parameters dictionary contains a null entry for parameter 'type' of non-nullable type 'CompetitionManager+MiniLeagueType' for method 'System.Collections.Generic.List`1[Competition] Get(Int32, MiniLeagueType)' in 'LeaguesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter." }

I am using AttributeRouting to decorate the methods, but this doesn't seem to work. It was working fine before I introduced MiniLeagueType.

Has anyone come across this issue, or can you point me to where I am going wrong?


Solution

  • I think that the cause is this url : api/Leagues/GetMiniLeagueTable/3. This url matches both routes, as it can be interpreted as such : api/Leagues?type=GetMiniLeagueTable&id=3. But it cannot convert GetMiniLeagueTable as a CompetitionManager.MiniLeagueType value, so it raises an error.

    You should make more specific routes, for example api/Leagues/GetCompetitions/{type}/{id}, in order to prevent url matching 2 or more different routes.

    Another possibility is to invert your action orders, as it will check first action's route before going for the next one if the url doesn't match.