volosoft / castle-windsor-ms-adapter

Castle Windsor ASP.NET Core / Microsoft.Extensions.DependencyInjection Adapter
https://www.nuget.org/packages/Castle.Windsor.MsDependencyInjection
MIT License
85 stars 29 forks source link

An exception occurred: Cannot access a disposed object. #37

Closed zengqinglei closed 3 years ago

zengqinglei commented 4 years ago

Instructions When I use HttpClient and join HttpClientMessageHandler, an exception occurs:Cannot access a disposed object.

This exception occurs when I request more than twice

Run Environment .net core: 2.2 castle.windsor: 5.0.1

Minimal repro steps

  1. Create asp.net core 2.2 api project

    
    <Project Sdk="Microsoft.NET.Sdk.Web">
    
    <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    </PropertyGroup>
    
    <ItemGroup>
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.1" />
    <PackageReference Include="Castle.Windsor" Version="5.0.1" />
    <PackageReference Include="Castle.Windsor.MsDependencyInjection" Version="3.3.1" />
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    </ItemGroup>

2. Add service interface
```csharp
/// <inheritdoc />
public class RepoService : IRepoService
{
    private readonly HttpClient _httpClient;

    /// <inheritdoc />
    public RepoService(HttpClient client)
    {
        _httpClient = client;
    }

    /// <inheritdoc />
    public async Task<IEnumerable<GitHubIssue>> GetRepos()
    {
        var response = await _httpClient.GetAsync("repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadAsAsync<IEnumerable<GitHubIssue>>();

        return result;
    }
}
  1. Inject HttpClient in Startup

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
    services.AddTransient<ValidateHeaderHandler>();
    services.AddHttpClient<IRepoService, RepoService>(
        c =>
        {
            c.BaseAddress = new Uri("https://api.github.com/");
            c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
            c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
        })
        .AddHttpMessageHandler<ValidateHeaderHandler>();
    
    if (false)
    {
        return services.UseAutofac();
    }
    else
    {
        return services.UseWindsor();
    }
    }
  2. Use the Castle.Windsor container

    public static class ServiceCollectionExtension
    {
    public static IServiceProvider UseAutofac(this IServiceCollection services)
    {
        // create a container-builder and register dependencies
        var builder = new ContainerBuilder();
    
        // populate the service-descriptors added to `IServiceCollection`
        // BEFORE you add things to Autofac so that the Autofac
        // registrations can override stuff in the `IServiceCollection`
        // as needed
        builder.Populate(services);
    
        // this will be used as the service-provider for the application!
        return new AutofacServiceProvider(builder.Build());
    }
    
    public static IServiceProvider UseWindsor(this IServiceCollection services)
    {
        var windsorContainer = new WindsorContainer();
    
        return WindsorRegistrationHelper.CreateServiceProvider(windsorContainer, services);
    }
    }
  3. The code in ApiController is as follows:

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
    private readonly IRepoService _repoService;
    
    /// <inheritdoc />
    public ValuesController(IRepoService repoService)
    {
        _repoService = repoService;
    }
    
    // GET api/values
    [HttpGet]
    public async Task<IEnumerable<GitHubIssue>> Get()
    {
        return await _repoService.GetRepos();
    }
    }

    Demo code: https://github.com/zengqinglei/TestHttpClientHandlerDispose.git

Then after starting the project, the second time the page is refreshed, the following exception occurs: image

I use the Autofac container and it works fine! I hope to get your reply as soon as possible, thank you!

zengqinglei commented 4 years ago

@maliming Hi: Is there a repair plan for this problem? Thank you!

maliming commented 4 years ago

I have tried, there is indeed a problem as you said. Castle-windsor-ms-adapter will support net core 3.0. We need to wait for hikalkan to handle this problem, the problem is beyond my ability. :)

zengqinglei commented 4 years ago

@maliming ok!

maliming commented 3 years ago

Fixed by volosoft/castle-windsor-ms-adapter#38