BigPigVT
BigPigVT

Reputation: 1381

Dependency Injection unable to resolve service for type in .NET Core Function App running in Azure

Summary

I've been following the Microsoft guidance Use dependency injection in .NET Azure Functions to introduce some Dependency Injection (DI) into an Azure Function that our team is creating. When I run locally in Visual Studio 2017 and invoke the function using Fiddler or Postman everything works - I can debug hitting breakpoints and the service being provided via the DI setup are working correctly. When we deploy the same function into Azure, however, we get the following exception:

Unable to resolve service for type 'MyLibrary.ITelemetryClient' while attempting to activate 'MyFunctionApp.GetRemoteSystemsByFeature'.

Details

I have a library assembly (.NET Standard 2.0) that exposes an interface, ITelemetryClient, and a default implementation, ApplicationInsightsTelemetryClient. They're pretty straightforward bits of code - I don't think the implementation of these are important to the issue, so I'll skip them for now.

In the solution that defines our function app (.NET Core 2.2) I've made sure the right NuGet packages are installed:

I have created Startup which inherits from FunctionsStartup:

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

[assembly: FunctionsStartup(typeof(MyFunctionApp.Startup))]
[assembly: InternalsVisibleTo("MyFunctionApp.Tests")]

namespace MyFunctionApp
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<MyLibrary.ITelemetryClient, MyLibrary.ApplicationInsightsTelemetryClient>();
        }
    }
}

I then give my function a constructor that asks for the MyLibrary.ITelemetryClient:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using MyLibrary;
using MyRepository;
using MyService;

namespace MyFunctionApp
{
    public class GetRemoteSystemsByFeature
    {
        private readonly MyLibrary.ITelemetryClient _telemetryClient;

        public GetRemoteSystemsByFeature(MyLibrary.ITelemetryClient telemetryClient)
        {
            _telemetryClient = telemetryClient;
        }

        // snip - the rest shouldn't matter for this question
    }
}

So I think I've done everything right. And as I said when I debug locally the whole thing works and the correct ITelemetryClient implementation is used and successfully does its thing.

When it gets deployed into Azure, though, we get the error quoted above. The stack trace for that exception doesn't mention any of our code:

System.InvalidOperationException:
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService (Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at lambda_method (Anonymously Hosted DynamicMethods Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null)
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 42)
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 32)
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1+<>c__DisplayClass1_1.<.ctor>b__0 (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 20)
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 26)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 44)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor+ParameterHelper.Initialize (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 845)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor+<TryExecuteAsyncCore>d__16.MoveNext (Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.csMicrosoft.Azure.WebJobs.Host, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 116)

Any ideas?

Update

It was requested I share the contents of the extensions.json file:

{
  "extensions":[
    { "name": "Startup", "typeName":"MyFunctionApp.Startup, MyFunctionApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}
  ]
}

Upvotes: 4

Views: 21557

Answers (5)

Kaido
Kaido

Reputation: 3931

In my case I was missing [assembly: FunctionsStartup(typeof(MyFunctionApp.Startup))]

Upvotes: 2

tshallenberger
tshallenberger

Reputation: 2846

Ran into this exact problem, trying to deploy an Azure Function CosmosDB ChangeFeedListener. Locally ran fine, once deployed it couldn't find the dependencies to inject in Startup.

There is a long history of DI issues with Azure Functions. Went down a long rabbit hole for this one.

Problem: /publish/bin/extensions.json was being generated like this:

{
   "extensions":
    [
     { "name": "CosmosDB", 
       "typeName":"Microsoft.Azure.WebJobs.Extensions.CosmosDB.CosmosDBWebJobsStartup, 
        Microsoft.Azure.WebJobs.Extensions.CosmosDB, Version=3.0.7.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35"
     }
   ]
}

Instead of this:

{
   "extensions":
    [
     { "name": "Startup", "typeName":"<ProjectNamespace>.Startup, <ProjectNamespace>, 
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"},
     { "name": "CosmosDB", 
       "typeName":"Microsoft.Azure.WebJobs.Extensions.CosmosDB.CosmosDBWebJobsStartup, 
        Microsoft.Azure.WebJobs.Extensions.CosmosDB, Version=3.0.7.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35"
     }
   ]
}

Solution:

Remove Microsoft.NET.Sdk.Functions

Azure Function .csproj:

<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>

Upvotes: 0

BigPigVT
BigPigVT

Reputation: 1381

After uninstalling the Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator package from the MyFunctionApp and redeploying the dependency injection errors stopped and things started working correctly. Thanks to anyone who offered their insights, especially to Katy Shimizu.

Upvotes: 1

Jamie Hammond
Jamie Hammond

Reputation: 151

Ok after a lot of messing about, i just updated my Microsoft.NET.sdk.Functions to 1.0.28 and im now getting an application error so its got past the DI error. Try that and let me know how you get on.

Ok i see you are on 1.0.28, im using .netcore 2.1 if that helps?

Upvotes: 0

Joey Cai
Joey Cai

Reputation: 20067

You need to add Microsoft.ApplicationInsights.AspNetCore to your project and add this to your Startup.cs class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    ...
}

Upvotes: 0

Related Questions