问题
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?
回答1:
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.
回答2:
It looks like the url: /api/Leagues/GetMiniLeagueTable/3 would match both routes.
Assuming it matches the first route, it would then be unable to convert GetMiniLeagueTable to CompetitionManager.MiniLeagueType unless that was a valid enum value.
You second route probably needs to be tested first, and only if that fails to match the url, try the second.
Not having used attributerouting myself (though I have used the similar attribute routing in the latest web api) I'm guessing the ActionPrecedence will help.
Try
[GET("api/Leagues/{type}/{id}", ActionPrecedence = 2)]
And
[GET("api/Leagues/GetMiniLeagueTable/{id}", ActionPrecedence = 1)]
来源:https://stackoverflow.com/questions/19965409/multiple-gets-in-web-api-calling-wrong-action