Хотя вы, похоже, уже выделили проблему, я выполнил следующий интеграционный тест, чтобы воссоздать вашу проблему и объяснить причину ошибки.
[TestClass]
public class FBMessageControllerTests {
[TestMethod]
public async Task HttpClient_Should_Get_OKStatus_From_Post_To_FBMessage() {
using (var server = new TestServer()) {
var config = server.Configuration;
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var handlerMock = new Mock<IExceptionHandler>();
handlerMock
.Setup(m => m.HandleAsync(It.IsAny<ExceptionHandlerContext>(), It.IsAny<System.Threading.CancellationToken>()))
.Callback<ExceptionHandlerContext, CancellationToken>((context, token) => {
var innerException = context.ExceptionContext.Exception;
Assert.Fail(innerException.Message);
});
config.Services.Replace(typeof(IExceptionHandler), handlerMock.Object);
var client = server.CreateClient();
string url = "http://localhost/api/fbMessage";
var body = new { body = "Hello World" };
using (var response = await client.PostAsJsonAsync(url, body)) {
var message = await response.Content.ReadAsStringAsync();
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, message);
}
}
}
[Authorize]
public class FBMessageController : ApiController {
public string Get() {
return null;
}
[System.Web.Mvc.ChildActionOnly]
public SendResponse Send(ComplexType test) {
return null;
}
[System.Web.Mvc.ChildActionOnly]
public SendResponse SendImage(string x, string y) {
return null;
}
[HttpPost]
public SendResponse Post([FromBody]AnotherComplexType body) {
return null;
}
public void Put(string gbody) {
return;
}
public void Delete(string body) {
return;
}
}
public class SendResponse { }
public class ComplexType { }
public class AnotherComplexType { }
}
Который произвел следующий результат сообщение: были найдены
несколько действий, которые соответствуют запросу:
Отправить на MiscUnitTests типа + FBMessageControllerTests + FBMessageController
Сообщение от MiscUnitTests типа + FBMessageControllerTests + FBMessageController
Приведенное выше сообщение сообщает вам, в чем именно была проблема. Структура обычно говорит вам, почему вы получили определенные ошибки. Иногда вам нужно знать, где искать.
Ссылка на следующие Routing and Action Selection in ASP.NET Web API, вот почему у вас возникла проблема.
вот алгоритм выбора действия.
- Создайте список всех действий на контроллере, соответствующих методу HTTP-запроса.
- Если в словаре маршрута есть запись «действие», удалите действия, имя которых не соответствует этому значению.
- Постарайтесь, чтобы соответствовать параметрам действия к URI, следующим образом:
- Для каждого действия, получить список параметров, которые являются простым типом, где связывание получает параметр из URI. Исключить необязательные параметры.
- Из этого списка попытайтесь найти соответствие для каждого имени параметра либо в словаре маршрута, либо в строке запроса URI. Матчи: нечувствительны к регистру и не зависят от порядка параметров.
- Выберите действие, в котором каждый параметр в списке имеет совпадение в URI.
- Если больше одного действия соответствует этим критериям, выберите тот, который соответствует большинству параметров.
- Игнорировать действия с атрибутом [NonAction].
Шаг 3, вероятно, является самым запутанным. Основная идея заключается в том, что параметр может получить свое значение либо из URI, либо из тела запроса , либо из пользовательской привязки. Для параметров, которые поступают из URI, , мы хотим убедиться, что URI фактически содержит значение для этого параметра , либо в пути (через словарь маршрута), либо в строке запроса .
В качестве примера рассмотрим следующее действие:
параметр
public void Get(int id)
Идентификатор связывается с URI. Следовательно, это действие может только соответствовать URI, который содержит значение для «id», либо в словаре маршрута , либо в строке запроса.
Необязательные параметры являются исключением, поскольку они являются необязательными. Для необязательный параметр, это нормально, если привязка не может получить значение от URI.
Сложные типы являются исключением по другой причине. Сложный тип может связываться только с URI посредством пользовательской привязки. Но в этом случае структура не может заранее знать, будет ли параметр связывать с конкретным URI. Чтобы узнать это, нужно будет вызвать привязку. Целью алгоритма выбора является выбор действия из статического описания перед вызовом любых привязок. Поэтому из алгоритма сопоставления исключаются сложные типы .
После того, как действие выбрано, вызывается все привязки параметров.
Резюме:
- Действие должно соответствовать методу HTTP запроса.
- Имя действия должно соответствовать записи «действие» в словаре маршрута, если имеется.
- Для каждого параметра действия, если параметр берется из URI, имя параметра должно быть найдено либо в словаре маршрута , либо в строке запроса URI. (Необязательные параметры и параметры исключаются.)
- Постарайтесь сопоставить максимальное количество параметров. Лучшим совпадением может быть метод без параметров.
Надеется, что это поможет вам понять, почему вы получили «Множественные действия были найдены ...» сообщение.
Счастливое кодирование !!!
Сообщение об исключении обычно сообщает вам, какие действия противоречили друг другу. проверьте, есть ли какие-либо внутренние исключения, которые дают вам ключ. – Nkosi
взгляните на это http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api – Nkosi
Устранение неполадок Идея: хотя «Отправить» и «SendImage» не помечены как «Post», они могут общаться через Http Post - и могут иметь такую же «подпись», что и метод «Post». Используйте Fiddler, а также комментируйте «Отправить» и «SendImage», чтобы узнать, это путь к продолжению. –