JsonPatchDocument‹T› выдает ошибку 400 при вызове API

Я получаю сообщение «Код ответа не указывает на успех: 400 (неверный запрос)». ошибка при вызове HTTP PATCH в моем API. Это работает, когда я удаляю параметр [FromBody] JsonPatchDocument из моего метода API.

Есть идеи, почему?

Это asp.net core 3.1 restful API с интерфейсом Blazor (не то, чтобы это имело значение)....

+------------+
| Web Client |      
+------------+
public async Task<BoatDto> UpdateBoatPartialAsync(Guid clubId, Guid boatId, BoatForUpdateDto boatForUpdateDto)
{
    BoatDto boatDtoFromApi = null;

    var patchDoc = new JsonPatchDocument<BoatForUpdateDto>()
        .Replace(o => o.Name, boatForUpdateDto.Name)
        .Replace(o => o.Description, boatForUpdateDto.Description);

    var serializedPatchDoc = JsonConvert.SerializeObject(patchDoc);

    try
    {
        var _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri(https://localhost:44383);
        _httpClient.Timeout = new TimeSpan(0, 0, 30);
        _httpClient.DefaultRequestHeaders.Clear();

        var request = new HttpRequestMessage(HttpMethod.Patch, $"clubs/{clubId.ToString()}/boats/{boatId}");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Content = new StringContent(serializedPatchDoc);
        request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json-patch+json");

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<BoatDto>(content);

    }
    catch (Exception ex)
    {
        throw;
    }

    return boatDtoFromApi;
}

+-----+
| API |     
+-----+     
[AllowAnonymous]
[ApiController]
[Route("clubs/{clubId}/boats")]
public class BoatsController : ControllerBase
{
    private readonly ClubRepo _clubRepo;
    private readonly BoatRepo _boatRepo;
    private readonly IMapper _mapper;

    public BoatsController(ClubRepo clubRepo, BoatRepo boatRepo, IMapper mapper)
    {
        _clubRepo = clubRepo ?? throw new ArgumentNullException(nameof(clubRepo));
        _boatRepo = boatRepo ?? throw new ArgumentNullException(nameof(boatRepo));
        _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
    }

    [HttpPatch]
    [Route("{boatId}")]
    public ActionResult UpsertBoatPartial(Guid clubId, Guid boatId, [FromBody] JsonPatchDocument<BoatForUpdateDto> boatPatchDocDto)
    {
        return Ok(); //never gets called
    }

    //[HttpPatch]
    //[Route("{boatId}")]
    //public ActionResult Test(Guid clubId, Guid boatId)
    //{
    //    return Ok(); //will get called
    //}

}

+-----+
| DTO |     
+-----+ 
public class BoatForUpdateDto
{
    public string Name { get; set; } 
    public string Description { get; set; } 
}

public class BoatDto
{
    public Guid ClubId { get; set; }
    public Guid BoatId { get; set; } 
    public string Name { get; set; }
    public string Description { get; set; }         
}

person inliner49er    schedule 01.04.2020    source источник


Ответы (1)


Получил работу! Мне пришлось добавить следующее в файл startup.cs моего API:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddControllers(setupAction =>
    {
        setupAction.ReturnHttpNotAcceptable = true;
    })
    .AddXmlDataContractSerializerFormatters()
    .AddNewtonsoftJson(setupAction => setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()
    );
    ...
}
person inliner49er    schedule 01.04.2020