Reputation: 1381
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'.
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?
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
Reputation: 3931
In my case I was missing [assembly: FunctionsStartup(typeof(MyFunctionApp.Startup))]
Upvotes: 2
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
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
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
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