SkinnyPete63
SkinnyPete63

Reputation: 653

System.ArgumentNullException: Value cannot be null. (Parameter 'factory') when implementing IHTTPClientFactory

Following on from this question: Blazor Server Initiating Task Halts Application I am now trying to implement the IHttpClientFactory DI as recommended. I am following this article: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-7.0 and I am getting this error:

System.ArgumentNullException: Value cannot be null. (Parameter 'factory')
    at System.ThrowHelper.Throw(String paramName)
    at System.Net.Http.HttpClientFactoryExtensions.CreateClient(IHttpClientFactory factory)
    at DespatchProServer.Pages.Customers.CustomersHome.GetCustomerQuotes(Int32 customerId) in C:\path\to\CustomersHome.razor.cs:line 246
    at my.dot.notation.CustomersHome.CustomerRowSelectHandler(RowSelectEventArgs`1 args) in C:\path\to\CustomersHome.razor.cs:line 137
    at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
    at Syncfusion.Blazor.Grids.Internal.Selection`1.SelectByRow(Row`1 rowToSelect, MouseAndKeyArgs evt)
    at Syncfusion.Blazor.Grids.Internal.Selection`1.ValidateRowSelectionClick(Row`1 row, MouseAndKeyArgs e)
    at Syncfusion.Blazor.Grids.Internal.Selection`1.RowSelectionClickHandler(MouseAndKeyArgs e, ValueTuple`3 target)
    at Syncfusion.Blazor.Grids.Internal.Selection`1.ClickHandler(MouseEventArgs e, ValueTuple`3 target)
    at Syncfusion.Blazor.Grids.Internal.GridCellBase`1.CellClickHandler(MouseEventArgs e, Boolean IsCheckBox)
    at Syncfusion.Blazor.Grids.Internal.GridCell`1.<BuildRenderTree>b__0_5(MouseEventArgs e)
    at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
    at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

In Program.cs I have:

builder.Services.AddHttpClient();

And here is my minimum reproducible code:

public partial class CustomersHome
{

    private readonly IHttpClientFactory _httpClientFactory;

    public CustomersHome() { }

    public CustomersHome(IHttpClientFactory httpClientFactory) => _httpClientFactory = httpClientFactory;

    public IEnumerable<Quotation> customerQuotations = Array.Empty<Quotation>();

    public async Task CustomerRowSelectHandler(RowSelectEventArgs<Customer> args)
    {
        await GetCustomerQuotes(args.Data.customerId);
    }
        public async ValueTask GetCustomerQuotes(int customerId)
    {
        string url = string.Format(@"https://my.server.dns/quotations/customer/{0}", customerId);

        var httpRequestMessage = new HttpRequestMessage(
        HttpMethod.Get,
        url)
        {
            Headers =
            {
                { HeaderNames.Accept, "application/vnd.github.v3+json" },
                { HeaderNames.UserAgent, "HttpRequestsSample" }
            }
        };
        
        var httpClient = _httpClientFactory.CreateClient(); **-> This is line 246**
        HttpResponseMessage response = await httpClient.SendAsync(httpRequestMessage);
        if (response.IsSuccessStatusCode)
        {
            customerQuotations = await response.Content.ReadFromJsonAsync<IEnumerable<Quotation>>() ?? Enumerable.Empty<Quotation>(); ;
        }
    }
}

The call comes from a Syncfusion Grid on row select, not that I think that has any bearing on the outcome. Any pointers gratefully received.

Upvotes: 0

Views: 1710

Answers (1)

SkinnyPete63
SkinnyPete63

Reputation: 653

OK, got to the bottom of this. Bear in mind, I am not a developer, so don't laugh too much at me. On my razor page, added:

@inject IHttpClientFactory ClientFactory

Then on my code behind page changed the line:

var httpClient = _httpClientFactory.CreateClient();

To

var httpClient = ClientFactory.CreateClient();

and removed the constructors at the top of the class. Working perfectly now.

Upvotes: 1

Related Questions