Azure / Azure/azure-functions-dotnet-extensions

DI sample code works when Function App is v2 but not v3

Open
#40 5 comments 5 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
81
Forks
50
PR merge metrics
No merged PRs in 30d

Description

I cannot get dependency injection to work in Azure Functions (documentation [here](https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection)) using a v3 Function App with .NET Core 3.1. (it will work locally but fails when deployed to Azure) The **exact same code** does work when deployed to a v2 Function App with .NET Core 2.1. The [test code](https://github.com/nolanegly/AzureFunkDI) is forked from a sample maintained by a docs.microsoft.com contributor.

@fabiocav I apologize for how long these steps are, but I wanted to be sure the report was reproducible. Am I doing something wrong, or should I fallback to v2 for the next few weeks?

### Create a function app instance

Log in to my subscription and create a new Function App

#### Basics
![image](https://user-images.githubusercontent.com/135814/78278991-7c952e00-74dc-11ea-98b7-25d19927d8da.png)
* Create new resource group `fa-rg`
* Name function app `di-in-azure-func`

Note: even though I want to initially run this on .NET Core 2.1 to verify the sample code works, the only choice provided while doing initial setup is 3.1. We will adjust the runtime version after the function app instance is deployed.

Click “Next: Hosting”

#### Hosting
![image](https://user-images.githubusercontent.com/135814/78279198-cbdb5e80-74dc-11ea-9351-55d2fdc5e84d.png)

* Create a new storage account `diinazurefuncstore`.
* Change Plan type to `App service plan`. Create new plan called `di-in-azure-func-plan`.
* Change Plan sku and size to `B1`. (free option does not allow setting bitness of function app)

Click “Next: Monitoring”

#### Monitoring
![image](https://user-images.githubusercontent.com/135814/78279271-e6153c80-74dc-11ea-9fa9-106a8cdbd75f.png)
* Create a new App Insights `di-in-azure-func-ai`.

Click “Review + create”

#### Review + Create
![image](https://user-images.githubusercontent.com/135814/78279335-fb8a6680-74dc-11ea-8699-65ab85493e64.png)

Click “Create”. Wait for the deployment to finish. Once the deployment finishes, choose “Go to resource”.

![image](https://user-images.githubusercontent.com/135814/78279382-0f35cd00-74dd-11ea-91e6-971939249c36.png)

### Configure the function app instance for .NET Core 2

We need to adjust several settings for the sample code to run properly.

#### Set runtime version
Choose “Function app settings”. Note the runtime version is set to 3. Click `2`. Wait patiently.

![image](https://user-images.githubusercontent.com/135814/78279461-270d5100-74dd-11ea-891d-aeeee1510715.png)

#### Set bitness and always on
Go to Configuration. Choose the General settings tab.

![image](https://user-images.githubusercontent.com/135814/78279598-5fad2a80-74dd-11ea-87e9-de9400b1b8b0.png)

* Change Platform to 64bit. (we are compiling to 64bit)
* Change Always On to On. (troubleshooting convenience, prevent app from going to sleep)
* Choose “Save”. Confirm restarting is OK by choosing “Continue”.

### Deploy the sample code with .NET Core 2
I forked the official sample from https://github.com/mike-urnun-msft/AzureFunkDI to https://github.com/nolanegly/AzureFunkDI in order to upgrade the .NET Core version and demonstrate the problem. I checked out the code to `c:\dev\` resulting in a solution location of `c:\dev\AzureFunkDI`.

#### Build
On the master branch, **with no code changes to the sample**, publish the project. If the output directory `c:\dev\stage` already exists, delete it first. In a PowerShell prompt, navigate to the directory of the project and do `dotnet publish --configuration “Release” --self-contained -r “win-x64” --output “c:\dev\stage”`

![image](https://user-images.githubusercontent.com/135814/78279711-9420e680-74dd-11ea-962a-59fabaca3e89.png)

#### Compress
After building the project, compress the output into a single zip for deployment. If the file `c:\dev\stage\funkdi.zip` exists, delete it first. In a PowerShell prompt, do `Compress-Archive /dev/stage/* -DestinationPath “c:\dev\funkdi.zip”

![image](https://user-images.githubusercontent.com/135814/78279879-d34f3780-74dd-11ea-9a41-edcb6e43b574.png)

#### Deploy to Azure
To deploy the zip you must have installed the Azure CLI, [available here](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?view=azure-cli-latest) if you don’t already have it.

If needed, log in to Azure CLI by typing `az login` in PowerShell.

Deploy the zipped payload to the function app by typing `az functionapp deployment source config-zip -g fa-rg -n di-in-azure-func --src c:\dev\funkdi.zip`
* If you’ve made a different resource group name, app function name, or zip file location/name, substitute those values.

![image](https://user-images.githubusercontent.com/135814/78279947-e9f58e80-74dd-11ea-917f-3903f51248db.png)

### Verify the sample code works in v2
Navigate to the function app. On the left side, select “HttpTrigger”. Wait patiently. On the right side, select the “Test” tab.
* Change the HTTP method to GET.
* Under Query, Choose “Add parameter”. Use “name” and “demo”.
* Choose “Run” button at the bottom of the Test panel (you may have to scroll down to see it).

In the bottom of the Test panel, the Output pane will say “Hello demo!” with a Status of “200 OK”. There will be no errors in the Logs pane.

![image](https://user-images.githubusercontent.com/135814/78279986-fbd73180-74dd-11ea-9689-d526aa08e05b.png)

### Adjust code to .NET Core 3
On your local development machine, change branches from “master” to “upgrade-to-core-31” (again, this on the repository https://github.com/nolanegly/AzureFunkDI)

Observe the only changes are setting the project to .NET Core 3, Function App version 3, and the corresponding SDK dll to 3.0.5.

![image](https://user-images.githubusercontent.com/135814/78280060-1ad5c380-74de-11ea-89c3-c61d6bf635d1.png)

### Deploy the sample code with .NET Core 3
Delete the previously built `c:\dev\funkdi.zip` file and `c:\dev\stage` directory.
Publish the project with `dotnet publish …` as done previously.
Compress the project with `Compress-Archive …` as done previously.
Deploy the package with `az functionapp …` as done previously.

### Configure the function app instance for .NET Core 3
In the portal, go to the “Function app settings”. Change the Runtime version to 3. Wait patiently.

![image](https://user-images.githubusercontent.com/135814/78280145-3c36af80-74de-11ea-9f99-ab112a9d44db.png)

### Observe the sample code fails in v3
Navigate to the function app. On the left side, select “HttpTrigger”. Wait patiently. On the right side, select the “Test” tab.
* Change the HTTP method to GET.
* Under Query, Choose “Add parameter”. Use “name” and “demo”.
* Choose “Run” button at the bottom of the Test panel (you may have to scroll down to see it).

#### EXPECTED
The same results we got in the section “Verify the sample code works in v2”

#### ACTUAL
In the bottom of the Test panel, the Output pane will have a Status of “500 Internal Server Error”. There will be a dependency injection failure in the error log.

`
System.InvalidOperationException : Unable to resolve service for type 'AzureFunkDI.IGreeter' while attempting to activate 'AzureFunkDI.HttpTrigger'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp,Type type,Type requiredBy,Boolean isDefaultParameterRequired)
at lambda_method(Closure ,IServiceProvider ,Object[] )
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider serviceProvider) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs : 37
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs : 32
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs : 20
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create(IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs : 26
at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx functionInstance) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs : 44
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize() at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs : 846
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance,CancellationToken cancellationToken) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs : 117
`

![image](https://user-images.githubusercontent.com/135814/78280306-7dc75a80-74de-11ea-8550-ff1e2dc1cb37.png)

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the linked AzureFunkDI sample, comparing its master and upgrade-to-core-31 branches, then follow the documented deployment steps for Function App versions 2 and 3. Reproduce the HTTP trigger request and inspect the error log. Done means the v3 deployment returns “Hello demo!” with status 200 and no dependency-injection failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp
Domain
backend, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.