C# 为什么某些参数类型会导致ASP.NET Web API中的路由不明确?
假设我有一个非常简单的路由表,如下所示:C# 为什么某些参数类型会导致ASP.NET Web API中的路由不明确?,c#,asp.net,asp.net-web-api,asp.net-web-api2,asp.net-web-api-routing,C#,Asp.net,Asp.net Web Api,Asp.net Web Api2,Asp.net Web Api Routing,假设我有一个非常简单的路由表,如下所示: routes.MapHttpRoute("root", "", new { controller = "Home", action = "Index" }); 在我的HomeController中,我有两种方法称为Index: [HttpGet] public IHttpActionResult Index() { return Content(HttpStatusCode.OK, new { service = "hard-coded
routes.MapHttpRoute("root", "",
new { controller = "Home", action = "Index" });
在我的HomeController
中,我有两种方法称为Index
:
[HttpGet]
public IHttpActionResult Index()
{
return Content(HttpStatusCode.OK, new { service = "hard-coded string" });
}
[HttpGet]
public IHttpActionResult Index(string a)
{
return Content(HttpStatusCode.OK, new { a });
}
如果我运行这个应用程序,就会像我预期的那样进行路由:如果我从查询字符串中省略a
参数,我的请求将被路由到第一个方法,如果我包含它,请求将被路由到第二个方法
但是,如果我将a
的类型更改为更复杂的类型,例如string[]
,那么当我在默认路由上发出请求时,我会得到以下错误(无论我是否指定了查询参数):
{
消息:“发生错误。”
ExceptionMessage:“找到多个与请求匹配的操作:类型SurveysApi.v1.Web.Controllers上的索引。类型SurveysApi.v1.Web.Controllers.HomeController上的HomeController索引”
异常类型:“System.InvalidOperationException”
StackTrace:“在System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext controllerContext)在System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore上执行同步(HttpControllerContext controllerContext,CancellationToken CancellationToken CancellationToken CancellationToken)(HttpRequestMessage请求,CancellationToken CancellationToken)位于System.Web.Http.Dispatcher.HttpControllerDispatcher.d_u0.MoveNext()
}
即使我在参数上指定FromUri
或ModelBinder
属性,错误仍然存在
除了在参数列表中指定简单类型和在控制器方法中执行必要的转换之外,为什么复杂类型会发生此错误?我建议您改用属性路由 在WebApiConfig.cs中启用它
config.MapHttpAttributeRoutes();
示例控制器为:
public class HomeController : ApiController
{
[Route("home/id/{Id}")]
[HttpGet]
public string Get(int Id)
{
return "id";
}
[Route("home/string/{str}")]
[HttpGet]
public string Get(string str)
{
return "string";
}
}
public class HomeController : ApiController
{
[ActionName("GetById")]
public string Get(int id)
{
return "id";
}
[ActionName("GetByGUID")]
public string Get(string id)
{
return "guid";
}
}
方法名称相同,但路由是关键因素。另一种方法是使用ActionName属性:
示例控制器为:
public class HomeController : ApiController
{
[Route("home/id/{Id}")]
[HttpGet]
public string Get(int Id)
{
return "id";
}
[Route("home/string/{str}")]
[HttpGet]
public string Get(string str)
{
return "string";
}
}
public class HomeController : ApiController
{
[ActionName("GetById")]
public string Get(int id)
{
return "id";
}
[ActionName("GetByGUID")]
public string Get(string id)
{
return "guid";
}
}
路线大致如下:
//Matches /api/Home/7
config.Routes.MapHttpRoute(
name: "DefaultDigitApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "GetById" },
constraints: new { id = @"^\d+$" } // id must be digits
);
//Matches /api/Home/CD73FAD2-E226-4715-B6FA-14EDF0764162
config.Routes.MapHttpRoute(
name: "DefaultGuidApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "GetByGUID" },
constraints: new { id = @"\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b" } // id must be guid
);
希望这至少有点帮助。这似乎是一个序列化问题,我不知道您使用的是什么编码,但当传递json对象时,序列化中会忽略空属性。这将导致默认url和对象(如空数组)在get请求中具有相同url的url,因此有两个操作适合该url