WebAPI HttpPost не получает размещенный контент от HttpClient

#c# #json #asp.net-core #asp.net-core-webapi #dotnet-httpclient

#c# #json #asp.net-core #asp.net-core-webapi #dotnet-httpclient

Вопрос:

Веб-API: я также пытался использовать [FormBody] и [FromForm] перед строкой stringcontent .

 // POST api/<MAUserController>
        [HttpPost("AuthenticateUser")]
        public async Task<ActionResult<MAUser>> PostAsync(string stringcontent)
        {
            //stringcontent is null
        }
  

Клиентский код:

 List<KeyValuePair<string, string>> postParameters = new List<KeyValuePair<string, string>>();
            postParameters.Add(new KeyValuePair<string, string>("Email", Email));
            postParameters.Add(new KeyValuePair<string, string>("Password", Password));
            var jsonString = JsonConvert.SerializeObject(postParameters);
            var stringContent = new StringContent(jsonString, Encoding.UTF8, "application/json");

            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenString);
                //httpClient.DefaultRequestHeaders.Add("Email", Email);
                //httpClient.DefaultRequestHeaders.Add("Password", Password);
                using (var response = await httpClient.PostAsync(API_URL, stringContent))
                {
                    if (response.IsSuccessStatusCode)
                    {
            //Success code
                    }
                    else
                    {
            //Handle unsuccessful here
                    }
                }
  

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

1. Длинный снимок: может быть, вам нужен API_URL "/AuthenticateUser" как URL?

2. Ни у одного API_URL уже нет правильного расположения URI. Точка останова действительно попадает в webapi во время отладки..

3. вы отправляете структурированные данные в формате JSON от клиента. Итак, почему API просто пытается принять простую строку? Это не имеет большого смысла. Вместо этого заставьте его принять объект модели с правильной структурой. ASP.NET позаботится о привязке свойств JSON к свойствам модели.

4. Разве вы не должны были ([FromBody] YourModel content) ? Где YourModel находится класс с соответствующими свойствами, которые необходимо десериализовать из json, который вы публикуете.

5. Кроме того, postParameters должно быть просто postParameters = new { Email = .., Password = .. };

Ответ №1:

Вы отправляете структурированные данные в формате JSON от клиента. Итак, почему API просто пытается принять простую строку? Это не имеет большого смысла.

Вместо этого вы должны заставить его принимать объект модели с правильной структурой. ASP.NET позаботится о привязке свойств JSON к свойствам модели. Тем не менее, вы также должны упростить и postParameters в клиенте — вы чрезмерно усложняете структуру.

например

Клиент:

 var postParameters  = new { Email = "abc@example.com", Password = "xyz" };
  

Сервер:

 public async Task<ActionResult<MAUser>> PostAsync([FromBody] UserCredentials credentials)
{
}
  

где UserCredentials находится класс DTO, подобный этому:

 public class UserCredentials
{
  public string Email { get; set; }
  public string Password { get; set; }
}
  

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

1. Может ли мой класс DTO UserCredentials иметь более двух свойств, даже если я задаю только два параметра? У меня уже есть объект DTO типа «MAUser», который имеет Email, Passowrd и другие свойства в этом классе.

2. Если TLS завершается с ошибкой, вы никогда не получите ответ, что означает отсутствие json!!! И нет ActionResult<MAUser>

3. Сбоя TLS нет, так как я получаю точку останова в webapi при «PostAsync»

4. @WinFXGuy _»Может ли мой класс DTO UserCredentials иметь более двух свойств, даже если я задаю только два параметра?» … да, безусловно. Связыватель модели просто проигнорирует любые свойства, которые не включены в JSON, и свяжет те, которые предоставлены.

Ответ №2:

итак, при использовании типа контента вы в основном сообщаете получающему API, как анализировать полезную нагрузку запроса, и поэтому, сообщая ему application / json, фреймворк пытается проанализировать полезную нагрузку из JSON в объект и присвоить ее вашему параметру (не совсем, поскольку вам нужно добавить атрибут [Frombody])но он не может этого сделать, поскольку вы ожидаете строку, поэтому либо измените тип вашего контента, либо измените тип вашего параметра (я бы предложил ваш тип параметра).