0

I got an ObjectDisposedException from my Index controller action when hitting refresh the page (i.e. requesting the page for a second time) and I suspect it's due to my incorrect usage of InRequestScope in Ninject.

A bit of background here, I have a CustomHttpClient class that wraps an HttpClient to send GET requests to a ASP.NET Web API:

public class CustomHttpClient : ICustomHttpClient
{
    private static readonly HttpMessageHandler HttpMessageHandler = 
        new HttpClientHandler { UseDefaultCredentials = true };

    private readonly HttpClient _httpClient;
    private bool _disposed;

    public CustomHttpClient(string uriString) : this(new Uri(uriString))
    {
    }

    public CustomHttpClient(Uri baseUri)
    {
        _httpClient = new HttpClient(HttpMessageHandler) { BaseAddress = baseUri };
        _httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
    }

    public async Task<HttpResponseMessage> GetAsync(string requestUri)
    {
        return await _httpClient.GetAsync(requestUri);
    }

}

My ASP.NET MVC controller takes this CustomHttpClient as a dependency:

public class CustomController : Controller
{
    private readonly ICustomHttpClient _customHttpClient;

    public CustomController(ICustomHttpClient customHttpClient)
    {
        _customHttpClient = customHttpClient;
    }

    public async Task<ActionResult> Index()
    {
        var response = await _customHttpClient.GetAsync("foo/bar");

        // Deserialize the response and return the view
        return View();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
        {
             return;
        }

        if (_httpClient != null && disposing)
        {
            _httpClient.Dispose();
        }

        _dispoed = true;
    }
}

My Ninject bindings:

public class CustomNinjectModule : NinjectModule
{
    Bind<ICustomHttpClient>()
        .To<CustomHttpClient>()
        .InRequestScope() // Should I use InCallScope() or InThreadScope() instead?
        .WithConstructorArgument(typeof(string), "http://foo.com");
}

My thinking is the HttpClient is already disposed after the request ends but the async task has not returned an HttpResponse yet, causing the ObjectDisposedException, is that correct?

rexcfnghk
  • 14,435
  • 1
  • 30
  • 57
  • *My thinking is the HttpClient is already disposed after the request ends but the async task has not returned an HttpResponse yet*. How could the request end before the async task returns? You're awaiting on it, that shouldn't happen. Also, why not use it for the lifetime of application? `HttpClient` shouldn't be disposed per request. – Yuval Itzchakov Feb 17 '15 at 07:37
  • (1) Is there any reason your Web page cannot call the WebAPI directly through AJAX, or is there any reason that your Controller itself cannot contain the logic that you are now putting in the WebAPI? and (2) Why do you need a fresh WebClient upon every request? – Roy Dictus Feb 17 '15 at 07:45
  • @YuvalItzchakov, I thought `HttpClient` should be similar to how a EF `DbContext` be used. Most will recommend setting `DbContext` to be `InRequestScope`, is this not the case for `HttpClient`? – rexcfnghk Feb 17 '15 at 07:51
  • Nope, that is definitely not the case for `HttpClient`. Read [this](http://stackoverflow.com/questions/15705092/do-httpclient-and-httpclienthandler-have-to-be-disposed) for a broader explanation. – Yuval Itzchakov Feb 17 '15 at 07:54
  • @RoyDictus, the WebAPI I am calling is an external one and I want to do some additional processing before sending the request to the actual API – rexcfnghk Feb 17 '15 at 08:30

0 Answers0