2

Предположим, у меня есть очень простую таблицу маршрутизации, как это:Почему некоторые типы параметров вызывают неоднозначную маршрутизацию в ASP.NET Web API?

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[], а затем, когда я сделать запрос на маршрут по умолчанию, я получаю следующее сообщение об ошибке (независимо от того, я указал параметр запроса):

{ 
    Message: "An error has occurred." 
    ExceptionMessage: "Multiple actions were found that match the request: Index on type SurveysApi.v1.Web.Controllers.HomeController Index on type SurveysApi.v1.Web.Controllers.HomeController" 
    ExceptionType: "System.InvalidOperationException" 
    StackTrace: " at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext) at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()" 
} 

ошибка остается, если даже если я указываю FromUri или ModelBinder атрибуты параметра.

Почему эта ошибка возникает для сложных типов, и есть ли способ избежать ее, если не указать простой тип в списке аргументов и выполнить необходимые преобразования в методе контроллера?

+0

похоже, что это может быть проблема с сериализацией, я не знаю, какую кодировку вы используете, но когда передаваемый json-объект передается атрибуты, которые являются нулями, просто пропущены из сериализации. это вызовет URL-адрес по умолчанию и URL-адрес, чтобы объект, такой как нулевой массив, имел один и тот же URL-адрес в запросе на получение, так что да, было бы два действия, которые соответствуют этому URL-адресу – theDarse

ответ

1

Перегрузка метода, похоже, не очень хорошо работает с веб-API. Вместо этого рекомендуется использовать маршрутизацию атрибутов.

Включите его в 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"; 
    } 
} 

Имена методов одинаковы, но маршруты являются ключевым фактором. Другим способом вы можете сделать это с помощью атрибута ActionName:

Примера Контроллера будет:

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 
); 

Надеется, что это помогает, по крайней мере немного.