Home > other >  HttpClient - Request was canceled - Timeout of 100 seconds elapsing
HttpClient - Request was canceled - Timeout of 100 seconds elapsing

Time:10-02

I am using a blazor web assembly project followed by a asp.net core web api and a shared project. When running my two projects and pulling up post man to perform a GET request https://localhost:5011/api/WebReport/GatherAllReports it hits the ReporterRepository from the blazor web assembly and when it hits the very first line var response it stays on that line then eventually after a really long time it says on postman...

System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

---> System.TimeoutException: The operation was canceled.

---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.

---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..

---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.
--- End of inner exception stack trace ---

at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)

at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16 token)

at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)

at System.Net.Http.HttpConnection.FillAsync(Boolean async)

at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean async, Boolean foldedHeadersAllowed)

at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)

--- End of inner exception stack trace ---

at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)

at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)

at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)

at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)

at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)

--- End of inner exception stack trace ---

and much more other messages returned in postman.

Is there a reason why this is occurring whenever I call the route endpoint for my web api controller?

Web API Controller:

using BlazorReports.Services; // this contains the `ReporterRepository.cs` file

[Route("api/[controller]")]
[ApiController]
public class WebReportController : ControllerBase
{
    
    private readonly ReporterRepository_repo;

    public WebReportController (ReporterRepository repo)
    {
        _repo = repo;
    }

    [HttpGet]
    [Route("GatherAllReports")]
    public async Task<IActionResult> Get()
    {
        var reportValues = await _repo.GetAll();
        return Ok(reportValues);
    }

}

startup.cs for web api:

public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{

    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebAPI", Version = "v1" });
    });
    services.AddDbContext<ReportContext>(options =>
          options.UseSqlServer(Configuration.GetConnectionString("Default")));

    services.AddScoped<IReporterRepository, ReporterRepository>();

    services.AddHttpClient<IReporterRepository, ReporterRepository>(client =>
        {
            client.BaseAddress = new Uri("https://localhost:5011/");
        });

    services.AddHttpContextAccessor();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebAPI v1"));
    }

    app.UseHttpsRedirection();

    app.UseCors(opt => opt
          .AllowAnyMethod()
          .AllowAnyHeader()
          .SetIsOriginAllowed(origin => true) 
          .AllowCredentials()); 

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

}

In my blazor web assembly project:

IReporterRepository.cs:

public interface IReporterRepository
{
    Task<List<Reports>> GetAll();
}

ReporterRepository.cs:

public class ReporterRepository: IReporterRepository
{
   
    private readonly HttpClient _httpClient;
    private readonly JsonSerializerOptions _options;

    public ReporterRepository(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
    }

    public async Task<List<Reports>> GetAll()
    {
        var response = await _httpClient.GetAsync("/ReportsPage/GatherAllReports");
        var content = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new ApplicationException(content);
        }

        var results = JsonSerializer.Deserialize<List<Reports>>(content, _options);
        return results;
    }

}

CodePudding user response:

Your request is timing out because you have created an infinite loop.

WebReportController.Get() invokes ReporterRepository.GetAll() which in turn makes an HTTP request back to WebReportController.Get() and you're back where you started. For the pattern you appear to be using, where your controller actions call into a service class to perform business logic (which is a good pattern), you would call into your Data Access Layer where your report data is held. You are not actually retrieving any report data in the code you have provided.

For example:

public async Task<List<Reports>> GetAll()
{
    var reportA = await _reports.GetReportA();
    var reportB = await _reports.GetReportA();

    // do any further business logic or error handling here

    return new List<Reports> { reportA, reportB };
}

CodePudding user response:

You are going in infinite loop because your GetAll() method is calling itself. Your code should look like this:

public class ReporterAccessLayer
{
   
    private readonly HttpClient _httpClient;
    private readonly JsonSerializerOptions _options;

    public ReporterAccessLayer(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
        _repository = repository;
    }

    public async Task<List<Reports>> GetAll()
    {
      try
      {
         return await httpClient.GetAsync<List<Reports>>("/ReportsPage/GatherAllReports");
      }
      catch
      {
         // do exception handling

      } 
    }

}
  • Related