Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.95k stars 442 forks source link

Dependency Injection issue: Unable to resolve service for type ... while attempting to activate [TimerFunction] #4939

Closed adamgd closed 4 years ago

adamgd commented 5 years ago

Injecting a DocumentClient instance works fine when debugging a Function locally but not on Azure. Possibly the same symptom as #4187.

Investigative information

Please provide the following:

Repro steps

Configure DocumentClient as a service:

public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IDocumentClient>(s =>
                new DocumentClient(new Uri(GetEnvironmentVariable("DatabaseAcctEndPoint")), GetEnvironmentVariable("DatabaseAcctKey") ));
        }
    }

... and then inject:

public class TimerClass
{
    [snip]
    private IDocumentClient _documentClient;

    public TimerClass(IDocumentClient documentClient)
    {
        _documentClient = documentClient;
    }

Expected behavior

The above code works fine when running in Debug locally (whether connecting to CosmosDB emulator or Azure-hosted CosmosDB) but not when the function is hosted on Azure.

Actual behavior

Exception thrown:

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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 37)
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance (Microsoft.Azure.WebJobs.Host, Version=3.0.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 20)
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create (Microsoft.Azure.WebJobs.Host, Version=3.0.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 26)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance (Microsoft.Azure.WebJobs.Host, Version=3.0.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 44)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor+ParameterHelper.Initialize (Microsoft.Azure.WebJobs.Host, Version=3.0.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 846)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor+<TryExecuteAsyncCore>d__16.MoveNext (Microsoft.Azure.WebJobs.Host, Version=3.0.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35Microsoft.Azure.WebJobs.Host, Version=3.0.13.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.13.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35: 117)

Related information

I think this is the same as, or similar to, #4187. As @fabiocav suggested at the end of that issue, I'm opening this as a new issue.

ThatBlokeCalledJay commented 5 years ago

I've just started getting the same issue locally. I was following this thread for answers https://github.com/Azure/azure-functions-host/issues/4187#issuecomment-511087567

I deployed the function about a month ago (it's still deployed and running). I've just opened up the code in VS2019, hit run to test locally and am getting the DI service not found exception. No code changes were made, and I haven't updated my nuget packages. My Startup.Configure method doesn't seem to be getting hit at all now

image

This is what my packages look like.

image

image image

I tried Pragnas's suggestion (https://github.com/Azure/azure-functions-host/issues/4187#issuecomment-476389427) of specifying a build executable,

image

image

I had quite a few to choose from, but still got the same error, with all of them.

Any ideas.

nb. I just deployed the function to Azure, and it is working. It's only locally I'm getting this error.

fabiocav commented 5 years ago

@ThatBlokeCalledJay would it be possible to share a repro so we can take a closer look at your function and registration?

I've noticed you're missing version 2.33.0, which was a preview with a resolution fix for validation. Have you tried to follow the instructions here ?

fabiocav commented 5 years ago

@adamgd can you please validate with the steps linked above as well?

ThatBlokeCalledJay commented 5 years ago

Hey @fabiocav yes, let me follow the instructions in the link you've provided, then if it still has issues i'll create and share the repo.

Hmm, wonder why I didn't get notified you'd responded 🤔

ThatBlokeCalledJay commented 5 years ago

On second thoughts I quickly created supper skinny test, which also fails exactly the same as above.

https://github.com/ThatBlokeCalledJay/azure-function-di-test

If I simply run that guy up and hit the endpoint suggested from a browser

http://localhost:7071/api/Function1

image

So as above, but with this super skinny function.

I created this guy, like so:

image

image

Then added the NuGet

image

I'm going to go try follow those instructions now.

Also, I'm using VS2019 Pro on Windows 10 Pro.

ThatBlokeCalledJay commented 5 years ago

@ThatBlokeCalledJay would it be possible to share a repro so we can take a closer look at your function and registration?

I've noticed you're missing version 2.33.0, which was a preview with a resolution fix for validation. Have you tried to follow the instructions here ?

So here's me doing that ^^^

image

So far so good...

image

Swish...

image

No whistles or bells...

image

H-ok... let's do this

image

Sad times...

ghost commented 5 years ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

adamgd commented 5 years ago

I have just tried a simple case like the one posted by @ThatBlokeCalledJay above, after following the instructions posted by @fabiocav. The only significant difference is that mine is a Timer Trigger. The function works with simple injected Singleton service class both locally and on Azure.

image

Result of hitting url https://<functionappname>.azurewebsites.net/admin/host/status?code=<masterkey>:

    {
    [snip]
    "state":"Running",
    "version":"2.0.12620.0",
    "versionDetails":"2.0.12620.0
    [snip]
    }

I will try to deploy my applied function against the same preview and report how it goes.

T-rav commented 4 years ago

I had the same problem. I fixed it by REMOVING the Microsoft.Azure.Functions.Extensions NuGet package. As soon as I did this IoC worked and I can debug.

kevinbuhmann commented 4 years ago

I am having this issue after updating to AzureFunctionsVersion v3. It worked fine with v2. Is there another issue tracking v3 dependency injection issues or is that covered by this issue?

fabiocav commented 4 years ago

@kevinphelps there are a few different issues here and many around issues prior to GA.

Can you please open another issue with the details of what you're seeing?

kabirshaikh commented 4 years ago

I am having this issue as well. More specifically, it works locally, but fails on Azure. I have tried the various proposed solutions mentioned in this thread, but nothing has worked. Is this issue being worked on?

jonathanantoine commented 4 years ago

Same issue and behavior than @kabirshaikh . Any help would be appreciated.

fabiocav commented 4 years ago

@kabirshaikh @jonathanantoine can you please open a separate issue with the details of the error you're seeing, including the runtime version you're using? If you have a repro you can share, that would be great!

fabiocav commented 4 years ago

@adamgd just wanted to check if this is something you're still seeing with your setup. Can you please confirm?

ghost commented 4 years ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

ThatBlokeCalledJay commented 4 years ago

This hasn't gone stale and certainly shouldn't be closed. I've been waiting quietly for a resolution. I dont see any resolutions posted on this thread and recent testing is still failing. In addition, my problem, as detailed above, is failing locally, but works when deployed to Azure.

fabiocav commented 4 years ago

@ThatBlokeCalledJay are you seeing the problem with the same setup as described in the original issue? Would you mind opening a separate issue with the details of what you're seeing and a repro?

shraddhaagrawal commented 4 years ago

We were facing same issue for version 2.0.12961.0 and issue got resolved after updating default host.json

Before- { "version": "2.0", "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[1.*, 2.0.0)" } }

Working- { "version": "2.0" }

paonekumar commented 4 years ago

it is working after removing extensionBundle from host.json, but looks like it is impacting performance

adiazcan commented 4 years ago

It's working also for me, removing extensionBundle and version 1.* fix the problem.

One question, Why the host file has this options? I have a blank host.json on my project and something generate this wrong content

shraddhaagrawal commented 4 years ago

@adiazcan This is default host.json You have to change properties of host.json file to copy always.

noant commented 4 years ago

I found that if IWebJobsStartup.Configure method is async and there is awaitable calls in this method, then "Unable to resolve service for type..." exception is thrown.

Not works:

public async void Configure(IWebJobsBuilder builder) // async method
{
    var backupConfiguration = await configurationReader.ReadConfiguration<BackupConfiguration>(configurationName);
    new Startup().Configure(builder.Services, backupConfiguration);
}

Works:

public void Configure(IWebJobsBuilder builder) // non-async method
{
    var backupConfiguration = configurationReader.ReadConfiguration<BackupConfiguration>(configurationName).Result;
    new Startup().Configure(builder.Services, backupConfiguration);
}
kabirshaikh commented 4 years ago

I have tried all of these solutions and it is still not working for me. This should NOT be closed.

briandunnington commented 4 years ago

Removing the extensionBundles from host.json like @shraddhaagrawal suggested solved it for us. Any idea on why this behavior changed recently? Took a long time to stumble upon this GitHub issue and solution.

jenol commented 4 years ago

I started having this issue after upgrading Microsoft.NET.Sdk.Functions to 3.0.3. Downgrading to 1.0.31 fixed the problem for me. I hope it helps.

briandunnington commented 4 years ago

@fabiocav This has been having huge impacts on use. We have v2 functions that have been running for months with no deployments that started breaking. The host.json file has been modified to

{ "version": "2.0", "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[1.*, 2.0.0)" } }

and it caused these 'Unable to resolve service for type...' errors. Manually editing the host.json back to just { "version": "2.0" } solved it, but it took forever to figure out what the cause was. The worst part is that the portal showed that the functions were started and running the whole time so we didn't know that the service was not starting properly.

What was the reason for the change? Should we expect it will happen to all of our services?

ThatBlokeCalledJay commented 4 years ago

@ThatBlokeCalledJay are you seeing the problem with the same setup as described in the original issue? Would you mind opening a separate issue with the details of what you're seeing and a repro?

@fabiocav of course I am. You'd like me to copy the verbose information + pictures + link to an example repo I posted above to a new thread? 90% of all information on this thread has been provided by me, heaps of info, images and the requested repo. I think a better idea would be for you to re-open this thread as it should never of been closed in the first place. I am having exactly the same issue now as I was having when I detailed my first issues.

I've already put in the leg work trying to detail as much as I can to help resolve the issue. Sorry if I didn't keep poking the thread every 15 minutes to keep it alive.

JVaughan1978 commented 4 years ago

I've just gone a round with this issue @ThatBlokeCalledJay and I believe that what you might have ran into but not realized it was actually a configuration with your csproj file you probably needed to include something akin to this: `

PreserveNewest
<None Update="local.settings.json">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>`

Most likely your host.json and local.settings.json weren't propagating and if you get the auto generated host.json it will error out on Dependency injection.

ThatBlokeCalledJay commented 4 years ago

Sadly @JVaughan1978 that doesn't seem to be the problem I'm having. even the demo repo I posted a link to above has that very configuration.

https://github.com/ThatBlokeCalledJay/azure-function-di-test

ThatBlokeCalledJay commented 4 years ago

Ok, so I've just created an azure function using sdk 3.0.3 and all seems to be working fine. I don't have that much invested where I can't just shift/upgrade my functions so I'll just do that.

bobwah commented 4 years ago

works for 3.0.3 after updating to 3.0.4 no longer hitting breakpoints and receiving the dependency injection error above.

rmbrunet commented 4 years ago

Same as @bobwah, simplest solution works well locally with sdk 3.03 but not with sdk 3.0.4!

ThatBlokeCalledJay commented 4 years ago

🤦🏻‍♂️

Dave76 commented 4 years ago

I also wanted to confirm that DI is busted with 3.0.4 sdk. Works fine with 3.0.3. I just had to downgrade my new solution in order get DI working.

ilushka85 commented 4 years ago

Di working fine in 3.0.3 for us... updating to 3.0.4 breaks it.

jasonshave commented 4 years ago

I can also confirm the same. Fought with this for the past day or two and finally found this post. Downgraded to 3.0.3 and it works again!

petr-stupka commented 4 years ago

seems like this has been fixed in 3.0.5 released yesterday

nmaroine commented 4 years ago

@petr-x no, I'm still having the same problem ...

rmbrunet commented 4 years ago

I'm OK in 3.0.5

lvnre commented 4 years ago

Encountering the same DI error. Upgrading from 3.0.1 to 3.0.5 did not resolve the error. Removing extensionBundles from bin/Debug/netcoreapp3.1/host.json did resolve the error

petr-stupka commented 4 years ago

@Invre Actually it is combination of both. Upgrade to 3.0.5 and remove the ExtensionBundles. Tested with 3.0.4 without bundles it didn’t worked.

rameshjanjyam commented 4 years ago

I found that if IWebJobsStartup.Configure method is async and there is awaitable calls in this method, then "Unable to resolve service for type..." exception is thrown.

Not works:

public async void Configure(IWebJobsBuilder builder) // async method
{
    var backupConfiguration = await configurationReader.ReadConfiguration<BackupConfiguration>(configurationName);
    new Startup().Configure(builder.Services, backupConfiguration);
}

Works:

public void Configure(IWebJobsBuilder builder) // non-async method
{
    var backupConfiguration = configurationReader.ReadConfiguration<BackupConfiguration>(configurationName).Result;
    new Startup().Configure(builder.Services, backupConfiguration);
}

this helped in my case. I have async lambda and it didn't work. removing async (& await) helped

builder.Services.AddSingleton(async sp =>
            {
                var config = sp.GetService<IConfiguration>();
                var client = new CosmosClient(config["COSMOS_CONNECTION_STRING"]);

                await client.CreateDatabaseIfNotExistsAsync("eventstore", 400);
                await client.GetDatabase("eventstore").CreateContainerIfNotExistsAsync("app", "/id");
                return client;
            });