Метод Web API HttpPost всегда получает GET

#c# #http-post #asp.net-core-webapi #dotnet-httpclient #http-get

#c# #http-post #asp.net-core-webapi #dotnet-httpclient #http-get

Вопрос:

У меня есть контроллер веб-API с методом

 [HttpPost]
[Authorize]
[Route("[action]")]
public async Task<IActionResult> Authenticate(HttpRequestMessage msg)
{
     //msg.Method is always GET
     // msg.Content is null 

}
  

Я вызываю его из своего настольного приложения следующим образом:

 HttpClient client = new HttpClient(new HttpClientHandler(){AllowAutoRedirect = false});
foreach (var header in headers)
{
    client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
await client.PostAsync(requestUrl, content);
  

Но в методе веб-api свойство msg.Method всегда является GET и msg.Содержимое равно нулю

Это своего рода перенаправление или другое преднамеренное поведение, когда каждый запрос превращается в GET?

Я попытался изменить его на

 [Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend([FromBody]string request)
{
    return Ok();
}
  

но получил ‘BadRequest’ после вызова.

Единственное, что работает, это заменить string на dynamic:

 [Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend([FromBody]dynamic request)
{
    return Ok();
}
  

Комментарии:

1. Если вместо этого вы отправляете сообщение от Postman, отображается ли оно как GET или POST?

2. Каково пространство имен HttpPostAttribute ?

3. @mjwills это от Microsoft. AspNetCore. Пространство имен Mvc

Ответ №1:

К вашему действию направляются только запросы POST. Вы просто смотрите не в то место — вы пытаетесь привязать тело вашего запроса к HttpRequestMessage экземпляру. Очевидно, вы передаете здесь что-то еще.

Если вы ищете детали запроса, используйте Request свойство controller. Он заполняется из контекста contoller, который передается контроллеру во время активации:

 [Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend()
{
    // Request.Method is POST here
    return Ok();
}
  

Но вам не нужно использовать его для получения содержимого запроса. Пусть Asp.Net сделайте эту работу за вас — объявите класс model, который имеет те же свойства, что и сериализованный объект, который вы отправляете, и model binder выполнит работу по десериализации за вас:

 [Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend(YourModel blah)
{
    // model will be populated automatically from request body
    return Ok();
}
  

Примечание: Существует более простой способ отправки запросов json. Вы можете использовать расширение PostAsJsonAsync из System.Net.Http.Formatting.Расширение