У меня есть контроллер веб-API .NET 8 со следующим методом конечной точки:
[HttpPost()]
[Route("someRoute")]
[ProducesResponseType(typeof(SomeResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetSomething([FromForm] SomeComplexRequest request, CancellationToken cancellationToken)
{
//Map request to some MediatR command, send and get result
return Ok(result.Value);
}
То, что он на самом деле делает внутри, не имеет отношения к моей проблеме. Эта конечная точка отлично работала до того, как я представил Refit в своем проекте (я использовал специальные реализации HttpClient).
Класс SomeComplexRequest выглядит следующим образом:
public sealed class SomeComplexRequest
{
[Required]
[FromForm(Name = "SomeID")]
public Guid? SomeID { get; set; }
[Required]
[FromForm(Name = "Offset")]
public int? Offset { get; set; }
[Required]
[FromForm(Name = "Length")]
public int? Length { get; set; }
public SomeComplexRequest(Guid? someID, int? offset, int? length)
{
SomeID = someID;
Offset = offset;
Length = length;
}
public SomeComplexRequest()
{
}
}
Моя проблема в том, что мой метод Refit работает ТОЛЬКО, если он написан так:
[Post("/api/SomeController/someRoute")]
[Multipart]
Task<ApiResponse<IEnumerable<SomeResponse>>> GetSomething(string someID, int offset, int length);
Насколько я понимаю, ситуация между SomeID Guid и строкой заключается в том, что Refit фактически не поддерживает Guid в качестве типа параметра. Это не идеально, но на самом деле это не такая уж большая проблема, поскольку контроллер в конечном итоге все равно понимает этот параметр независимо от того, отправлен ли он в виде Guid или строки. Что меня крайне раздражает, так это то, что метод Refit, похоже, требует перечисления всех отдельных параметров, составляющих мой запрос, вместо того, чтобы просто принимать экземпляр SomeComplexRequest независимо от того, является ли идентификатор Guid или строкой. Кажется, он не может разбить запрос на отдельные параметры. Эта подпись не работает:
[Post("/api/SomeController/someRoute")]
[Multipart]
Task<ApiResponse<IEnumerable<SomeResponse>>> GetSomething(SomeComplexRequest request);
У меня есть множество конечных точек, не являющихся Multipart (аннотированных FromBody в методе контроллера API), и они отлично работают с аналогичными сложными объектами запросов (в которых также есть Guids, заметьте). Это один из них :
[Post("/api/SomeOtherController")]
Task<ApiResponse<SomeOtherResponse>> AddSomeComplexThing(SomeEvenMoreComplexRequest);
Я не буду показывать этот запрос для краткости, но он имеет 8 параметров, включая строки, Guids и Enums. Этот метод имеет FromBody в параметре метода конечной точки, и он работает нормально.
Ожидается ли, что методы Multipart не поддерживают сложные объекты в качестве входных параметров, как это делает обычный метод с телом JSON?
удаление [Multipart], возвращение моего сложного объекта в качестве параметра и аннотирование его с помощью [Body(BodySerializationMethod.UrlEncoded)], похоже, действительно помогает! Спасибо!





Моя проблема была частично связана с непониманием того, что такое многочастный запрос. Название вроде говорит само за себя, но это запрос, который состоит из нескольких запросов и обычно используется для загрузки файлов вместе с некоторыми метаданными.
Моя первая реализация конечной точки REST API FromForm должна была делать именно это, поэтому я ошибочно связал FromForm с Multipart, думая, что они должны идти вместе. Мой проблемный запрос здесь на самом деле представляет собой просто запрос с разбиением на страницы в форме, поэтому с самого начала в Multipart не было необходимости. Похоже, что именно аспект Multipart не позволяет использовать сложный объект в качестве параметра клиента. Как только я удалил его и указал [Body(BodySerializationMethod.UrlEncoded)] перед указанным объектом запроса, он начал работать.
Вы проверили документацию? У вас должна быть возможность опубликовать объект.