I have a Blazor Server C# application in .NET 9 and I use a service to handle remote API calls. I would like to set timeout for requests globally like this:
var timeoutSec = builder.Configuration.GetValue<int>("Main:ServiceTimeoutSec");
builder.Services.AddHttpClient<ApiService>((serviceProvider, client) =>
{
var config = serviceProvider.GetRequiredService<IConfiguration>();
var baseAddress = config["Api:ApiBaseAddress"] ?? "MISSING_BASE_ADDRESS";
client.BaseAddress = new Uri(baseAddress);
// HAS NO EFFECT -> client.Timeout = TimeSpan.FromSeconds(timeoutSec);
})
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(timeoutSec))); // API query timeout
The last line sets the Polly timeout.
When I set ServiceTimeoutSec in config to less than 30 seconds, then the Polly timeout works fine and throws TimeoutRejectedException. This is ok!
When I set ServiceTimeoutSec in config more than 30 seconds, for example 60 seconds, then the I get timeout exception after 30 seconds with this error message:
The operation didn't complete within the allowed timeout of '00:00:30'
Why is the code not using my 60 seconds setting in this case?
I use Visual Studio 2022 in development mode.
Thank you!
I try increase the client.Timeout but has no effect, so I commented out this line.
I check client.Timeout in service constructor, it shows the default 00:01:40.
I double check the DI and service, and the good HttpClient is constructed in the service.
Excepted result: when I set the timeout to 60 seconds, I would like use this timeout everywhere with this HttpClient instance.
I tried change SignalR connection timeouts:
Server side:
builder.Services.AddServerSideBlazor()
.AddHubOptions(options =>
{
options.MaximumReceiveMessageSize = 102_400_000;
options.KeepAliveInterval = TimeSpan.FromSeconds(80);
options.ClientTimeoutInterval = TimeSpan.FromSeconds(160); // ≥ 2 × keep-alive
options.HandshakeTimeout = TimeSpan.FromSeconds(10);
})
.AddCircuitOptions(options => { options.DetailedErrors = builder.Environment.IsDevelopment(); }); // Enable detailed errors
Client side:
<script src="_framework/blazor.web.js" autostart="false"></script>
<script>
Blazor.start({
configureSignalR: builder => builder
.withKeepAliveInterval(80000) // 80 s – must match server
.withServerTimeout(160000), // 160 s – ≥ 2 × keep-alive
reconnectionOptions: {
maxRetries: 10,
retryIntervalMilliseconds: 5000
}
});
window.Blazor.defaultReconnectionHandler._reconnectCallback = () => {
console.log("Blazor is reconnecting...");
};
</script>
I have no any extra webserver configuration, this is a simple Blazor Web App template in NET 9. If I good know this is a default Kestrel. I tried change some Kestrel settings in appsettings.json:
"Kestrel": {
"Limits": {
"KeepAliveTimeout": "00:02:00",
"RequestHeadersTimeout": "00:00:45",
}
}
The result is always same, timeout coming after 30 or 90 secods regardless of my settings...
executionTimeoutinside the applicationhost.config or appsettings.json