#c# #asp.net-core #asp.net-web-api #asp.net-web-api2 #asp.net-core-webapi
Вопрос:
У меня есть asp.net контроллер ядра веб-api, который работает совершенно нормально, он выполняет все строки и никогда не попадает в блок catch.
Он также добавляет и обновляет запись в CosmosDB. Я отладил его построчно, а затем удалил все точки останова, также проверенные в ComosDB, и все правильно.
Однако, когда я вызываю конечную точку не из Postmann, я получаю эту ошибку:
Как вы можете видеть, в стеке вызовов НЕТ моего кода:
System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout()
at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStackamp; state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, Tamp; value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStackamp; state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, Tamp; value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStackamp; state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, Tamp; value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, Tamp; value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValueamp; value, JsonSerializerOptions options, WriteStackamp; state)
at System.Text.Json.JsonSerializer.WriteAsyncCore[TValue](Stream utf8Json, TValue value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](Stateamp; next, Scopeamp; scope, Objectamp; state, Booleanamp; isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Мой Контроллер:
/// <summary>
/// Adds global design tenant
/// </summary>
/// <param name="globaldesigntenant">Global Design Tenant</param>
/// <returns>OK if no errors</returns>
[HttpPost]
public async Task<ActionResult> AddGlobalDesignTenant([FromForm]GlobalDesignTenant globaldesigntenant)
{
this.telemetry.TrackEvent("AddGlobalDesignTenant");
try
{
/*if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}*/
byte[] data = Convert.FromBase64String(globaldesigntenant.CertPfxFile);
// Converts the base 64 encoded cert to an X509Certicate instannce
var cert = new X509Certificate2(
data,
globaldesigntenant.CertificatePassword,
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var authManager = new AuthenticationManager(globaldesigntenant.AzureApplicationId,
cert,
globaldesigntenant.TenantId);
using (var context = authManager.GetContext(globaldesigntenant.TestSiteCollectionUrl))
{
context.Load(context.Web, p => p.Title);
context.ExecuteQuery();
};
//No exceptions here, it means the certificate and password are valid.
string certName = "GlobalDesignTenantPFXFileBase64-" globaldesigntenant.TenantId;
string secretName = "GlobalDesignTenantCertPassword-" globaldesigntenant.TenantId;
/// Adding the certificate password to the key vault
await _secretClient.SetSecretAsync(secretName, globaldesigntenant.CertificatePassword);
//Adding the certificate to keyvault (base 64 encoded)
await _secretClient.SetSecretAsync(certName, globaldesigntenant.CertPfxFile);
var added = await _globalDesignTenantCosmosStore.AddAsync(globaldesigntenant);
// These secrets are saved in KeyVault, not in CosmosDB.
added.Entity.CertificatePassword = string.Empty;
added.Entity.CertPfxFile = string.Empty;
var result = await _globalDesignTenantCosmosStore.UpdateAsync(added);
return Ok(result);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " guid);
}
}
Ответ №1:
Похоже, что это происходит во время сериализации вывода, которая выполняется в промежуточном программном обеспечении по умолчанию. Не уверен, что это ошибка в системе.Текст.Сериализатор Json, поскольку он не должен пытаться получить тайм-аут для потока ответов, или если какое-либо другое промежуточное программное обеспечение приводит к тому, что тайм-аут потока становится нечитаемым. Вы могли бы попробовать использовать промежуточное программное обеспечение newtonsoft json formatter вместо этого, чтобы проверить теорию?
Для этого добавьте пакет: Microsoft.AspNetCore.Mvc.NewtonsoftJson
и в сервисах конфигурации:
// replace
services.AddControllers();
// with
services.AddControllers().AddNewtonsoftJson();
Если это не поможет, возможно, поможет добавление какого-либо пользовательского промежуточного программного обеспечения. В этом промежуточном программном обеспечении вы заменили бы выходной поток http-контекста потоком, которым вы можете управлять, а затем вернули бы его обратно.
Ответ №2:
Это может быть что-то с заголовками ваших запросов почтальона, но я на это не рассчитываю. Если это ошибка сериализации на сервере, вы можете преобразовать результат в объект JSON
return Ok(JObject.fromObject(result)); //with newtonsoft
и посмотрите, обеспечивает ли это сериализацию или выдает более подробную ошибку.