0

I'm trying to have a function that has its dependencies injected as outlined in documentation, Use dependency injection in .NET Azure Functions. My Startup class is defined as:

    using System.Runtime.CompilerServices;
    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;

    [assembly: FunctionsStartup(typeof(MyFunctions.Startup))]

    namespace MyFunctions{    
      public class Startup : FunctionsStartup
      {
        public override void Configure(IFunctionsHostBuilder builder)
        {
          builder.Services.AddHttpClient();
        }
      }
    }

I set a breakpoint on the builder.Services.AddHttpClient() statement to ensure the DI is configured. Then I define my function using a HttpTrigger:

    using System;
    using System.Net.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Extensions.Logging;

    namespace MyFunctions
    {
        public class ChangeProducer
        {
            private readonly HttpClient _httpClient;

            public ChangeProducer(IHttpClientFactory httpClientFactory)
            {
                _httpClient = httpClientFactory.CreateClient();
            }

            [FunctionName("ChangeProducer")]
            public void Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Reservation")]HttpRequest request, ILogger log)
            {
                Console.WriteLine("foo");
            }
        }
    }

When I run this from Visual Studio I hit the breakpoint in Startup.Configure. Wonderful!

Then I change my function to use an EventGridTrigger:

    using System;
    using System.Net.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Extensions.Logging;

    namespace MyFunctions
    {
        public class ChangeProducer
        {
            private readonly HttpClient _httpClient;

            public ChangeProducer(IHttpClientFactory httpClientFactory)
            {
                _httpClient = httpClientFactory.CreateClient();
            }

            [FunctionName("ChangeProducer")]
            public void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
            {
                Console.WriteLine("foo");
            }
        }
    }

Once that change is made, and no other change, I don't hit the breakpoint in Startup.Configure. Additionally, I know the DI is failing because when I try to invoke the function I get an error message that reads:

    Executed 'ChangeProducer' (Failed, Id=06ae8b88-07c4-4150-91e5-8b88400aed72)
    Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'System.Net.Http.IHttpClientFactory' while attempting to activate 'MyFunctions.ChangeProducer'.

Is there a known issue? I can't figure this out. The only difference is the trigger type.

Update 2019-06-24 - It's just the dependency injection

I want to be clear the issue is dependency injection isn't working, there isn't an issue with the EventGridTrigger when the dependency on HttpClient is not injected. Change the constructor to the following and the function works fine when triggered by the EventGridTrigger:

    public ChangeProducer()
    {
        _httpClient = new HttpClient();
    }
BigPigVT
  • 1,381
  • 3
  • 12
  • 20
  • How are you testing the EventGrid triggered function? – Chris Jun 24 '19 at 15:54
  • Invoking the test URL via Postman http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname} – BigPigVT Jun 24 '19 at 17:28
  • Strange. Did you create the function from the EventGrid template? – Chris Jun 24 '19 at 20:19
  • Not sure - someone else on the team initially created this function and added a comment with the URL to test with (he's out today). FWIW it's just the dependency injection that seems to suffer. When I comment the constructor documented above and use a default constructor that sets `_httpClient = new HttpClient();` the function works fine via the `EventGridTrigger`. I'll update the post with that info for clarity. – BigPigVT Jun 24 '19 at 21:01
  • chris, I've confirmed the function was created via the EventGrid template. – BigPigVT Jun 25 '19 at 14:39
  • 1
    Ah okay. I'd recommend recreating it again via the template and see if that works? Maybe something has somehow got messed up – Chris Jun 25 '19 at 18:31

2 Answers2

0

I have successfully tested with the following packages and Visual Studio 2019, version 16.1.3.

enter image description here

The following screen snippets show the debugging steps:

  1. On the Start-up

enter image description here

  1. Invoking a function by POST

    http://localhost:7071/runtime/webhooks/EventGrid?functionName=Function1

enter image description here

enter image description here

Roman Kiss
  • 7,925
  • 1
  • 8
  • 21
  • Thanks for the information, Roman. You list a few of NuGet packages I didn't have installed; `Microsoft.Azure.WebJobs.Extensions.Http`, `Microsoft.Extensions.Http`, and `Microsoft.Extensions.DependencyInjection` - so I installed those (same versions you listed). Unfortunately, the dependency injection is still failing with the same error `Unable to resolve service for type 'System.Net.Http.IHttpClientFactory'...`. Next step is to start with fresh solution and see if I can get what you've provided to work locally. – BigPigVT Jun 25 '19 at 12:18
0

I've figured out the dependency injection issue after creating a new function app and slowly building it out and comparing to the project that was experiencing the problem. The host.json file contained a property named extensionBundle. Once I removed that the dependency injection started working again. The entire property looks like this:

    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[1.*, 2.0.0)"
    }
BigPigVT
  • 1,381
  • 3
  • 12
  • 20