Чтение DTO из HttpContext возвращает значение null при десериализации JSON (клиент, сгенерированный nswag).C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Гость
 Чтение DTO из HttpContext возвращает значение null при десериализации JSON (клиент, сгенерированный nswag).

Сообщение Гость »

Я погружаюсь в NET8, минимальный API и чистую архитектуру.
Прежде всего: это работает (пользовательский интерфейс Swagger и почтальон)

Код: Выделить всё

   app.MapPost("/user/login", async (HttpContext httpContext, [FromBody] LoginDto loginDto, [FromServices] IConfiguration conf, [FromServices] UserDataBackupDbContext db, [FromServices] UserManager userManager) =>
{
try
{
{... shortened ...}

var response = new AuthResponseDto
{
Id = user.Id,
UserName = user.UserName ?? Constants.UnknownValue,
Token = accessToken
};

return TypedResults.Ok(response);
}
catch (Exception e)
{
return Results.BadRequest(e.Message);
}
}).WithName("UserLogin")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.AllowAnonymous();
Через пользовательский интерфейс Swagger или Postman я получаю объект AuthResponseDto обратно.
Теперь я возился с генерацией клиента nswag. Созданный метод таков:

Код: Выделить всё

   /// 
A cancellation token that can be used by other objects or threads to receive notice of cancellation.
/// A server side error occurred.
public virtual async System.Threading.Tasks.Task UserLoginAsync(LoginDto loginDto, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
if (loginDto == null)
throw new System.ArgumentNullException("loginDto");

var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var json_ = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(loginDto, _settings.Value);
var content_ = new System.Net.Http.ByteArrayContent(json_);
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("POST");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));

var urlBuilder_ = new System.Text.StringBuilder();
if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
// Operation Path: "user/login"
urlBuilder_.Append("user/login");

await PrepareRequestAsync(client_, request_, urlBuilder_, cancellationToken).ConfigureAwait(false);

var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);

await PrepareRequestAsync(client_, request_, url_, cancellationToken).ConfigureAwait(false);

var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = new System.Collections.Generic.Dictionary();
foreach (var item_ in response_.Headers)
headers_[item_.Key] = item_.Value;
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}

await ProcessResponseAsync(client_, response_, cancellationToken).ConfigureAwait(false);

var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new UserDataBackupApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
if (status_ == 400)
{
var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new UserDataBackupApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
}
throw new UserDataBackupApiException("A server side error occurred.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
}
else
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new UserDataBackupApiException("The HTTP status code of the response was not expected ("  + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
Во время выполнения он получит ответ с длиной содержимого = 0.
Позже, в блоке status_ == 200, он прочитает ответ объекта и вернуть новый экземпляр (все значения по умолчанию, а не то, что было отправлено из API).
Вопросы:
  • Почему десериализованный объект не заполняется значениями из ответа?
  • Почему HttpCompletionOption ResponseHeadersRead? Если я вручную установил для этого параметра значение ResponseContentRead, длина содержимого будет >0, и я смогу получить содержимое в виде строки. Но остальная часть функции в любом случае вернет экземпляр «новорожденного».
  • Есть ли какой-либо параметр OpenApi или nswag, который я могу установить?
Для полноты: сгенерированная функция, читающая объект. В моем случае часть else попытается прочитать из потока:

Код: Выделить всё

   protected virtual async System.Threading.Tasks.Task ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary headers, System.Threading.CancellationToken cancellationToken)
{
if (response == null || response.Content == null)
{
return new ObjectResponseResult(default(T), string.Empty);
}

if (ReadResponseAsString)
{
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody = System.Text.Json.JsonSerializer.Deserialize(responseText, JsonSerializerSettings);
return new ObjectResponseResult(typedBody, responseText);
}
catch (System.Text.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
throw new UserDataBackupApiException(message, (int)response.StatusCode, responseText, headers, exception);
}
}
else
{
try
{
using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
var typedBody = await System.Text.Json.JsonSerializer.DeserializeAsync(responseStream, JsonSerializerSettings, cancellationToken).ConfigureAwait(false);
return new ObjectResponseResult(typedBody, string.Empty);
}
}
catch (System.Text.Json.JsonException exception)
{
var message = "Could not deserialize the response body stream as " + typeof(T).FullName + ".";
throw new UserDataBackupApiException(message, (int)response.StatusCode, string.Empty, headers, exception);
}
}
}
Если вам нужна дополнительная информация, просто спросите.
TIA

Подробнее здесь: https://stackoverflow.com/questions/781 ... tion-nswag
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»