Luis Valencia
Luis Valencia

Reputation: 34038

System.InvalidOperationException: Timeouts are not supported on this stream. at System.IO.Stream.get_ReadTimeout()

I have an asp.net web api core controller which works completely fine, it executes all lines and it never gets to the catch block.

It also adds and updates the record on CosmosDB. I debugged it line by line and then I removed all breakpoints also verified on ComosDB and everything is correct.

However when I call the endpoinnt from Postmann I get this error:

As you can see the call stack DOES NOT have any of my code:

System.InvalidOperationException: Timeouts are not supported on this stream.
   at System.IO.Stream.get_ReadTimeout()
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValue& value, JsonSerializerOptions options, WriteStack& 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](State& next, Scope& scope, Object& state, Boolean& 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)

My Controller:

 /// <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);
            }             
        }

Upvotes: 1

Views: 10708

Answers (2)

Luke Weaver
Luke Weaver

Reputation: 409

It could be something with your postman request headers, but I'm not banking on that. If it's a serialization error with the server, you could convert result into a JSON object

return Ok(JObject.fromObject(result)); //with newtonsoft

and see if that either ensures serialization or gives a more detailed error.

Upvotes: 0

Steve Harris
Steve Harris

Reputation: 5109

It looks like it's throwing during the output serialization which is done in the default middleware. Not sure if this is a bug in the System.Text.Json serializer as it shouldn't be attempting to get the timeout for the response stream, or if some other middleware is causing the stream's timeout to be unreadable. You could try using the newtonsoft json formatter middleware instead to test the theory?

To do this, add the package: Microsoft.AspNetCore.Mvc.NewtonsoftJson and in ConfigureServices:

// replace
services.AddControllers();
// with
services.AddControllers().AddNewtonsoftJson();

If that doesn't help, maybe adding some custom middleware might help. In this middleware you would replace the http context's output stream with a stream you can control then put it back afterwards.

Upvotes: 1

Related Questions