Система.Исключение InvalidOperationException: Тайм-ауты в этом потоке не поддерживаются. в System.IO.Stream.get_ReadTimeout()

#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
 

и посмотрите, обеспечивает ли это сериализацию или выдает более подробную ошибку.