React调用Web API触发System.InvalidOperationException错误排查
解决Web API调用GetSingle时的"Multiple actions were found"错误
问题背景
你有一个TestApiController,包含GetAllData和GetSingle两个GET方法,在React应用中调用GetSingle时遇到了多Action匹配的错误,尽管你添加了包含action参数的路由,但问题依然存在,且希望避免使用自定义路由属性。
相关代码
控制器代码(C#)
public IHttpActionResult GetAllData() { var modelitems = new List<TestModel>(); var items = AWEntity.GetProducts(); var i = 0; foreach (var item in items) { var model = new TestModel { Id = item.ProductId, TestName = item.Name, TestMessage = "My Message" + i, ReorderPoint = item.ReorderPoint }; modelitems.Add(model); i++; } return Ok(modelitems); } public IHttpActionResult GetSingle() { var item = AWEntity.GetProduct(); var model = new TestModel { Id = item.ProductId, TestName = item.Name, TestMessage = "My Message" + 1, ReorderPoint = item.ReorderPoint }; return Ok(model); }
React Fetch代码(JavaScript)
fetch('http://localhost:51620/api/TestApi/GetSingle') .then(result => result.json()) .then(result => { this.setState({ items : result } ) })
Web API路由配置(C#)
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
错误信息
{ "message": "An error has occurred.", "exceptionMessage": "Multiple actions were found that match the request: \r\nGetData on type WebAPIComponent.Controllers.TestApiController\r\nGetSingle on type WebAPIComponent.Controllers.TestApiController", "exceptionType": "System.InvalidOperationException", "stackTrace": " at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()" }
错误原因
核心问题是路由注册顺序导致的匹配优先级问题:
- Web API的路由匹配是按照你注册的顺序来的,你先注册了
DefaultApi路由(api/{controller}/{id}),它会优先匹配你的请求/api/TestApi/GetSingle——此时路由会把GetSingle解析为可选的id参数,而不是action名称。 - 当这个路由匹配成功后,Web API会去控制器中寻找符合GET请求的方法,但你的控制器里有两个以
Get开头的方法(GetAllData和GetSingle),Web API无法确定应该调用哪一个,因此抛出了"Multiple actions were found"的错误。 - 你后来注册的带
action参数的路由根本没有被匹配到,因为第一个路由已经先满足了匹配条件。
解决方案
调整路由的注册顺序,把包含action参数的API Default路由放在DefaultApi路由的前面:
// 先注册带action的路由,优先匹配 config.Routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); // 再注册默认路由,作为兜底 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
这样,当你请求/api/TestApi/GetSingle时,会优先匹配到带action参数的路由,Web API会根据action值找到对应的GetSingle方法,避免了多Action的歧义。
另外,虽然不是必须的,但为了让代码更清晰,建议给你的GET方法加上[HttpGet]属性(这不属于自定义路由属性,是HTTP动词属性),明确指定方法对应的HTTP请求类型,这样即使路由有变化,也能更准确地匹配:
[HttpGet] public IHttpActionResult GetAllData() { ... } [HttpGet] public IHttpActionResult GetSingle() { ... }
内容的提问来源于stack exchange,提问作者EmpJemz
相关产品推荐
相关产品推荐

