Azure-functions-durable-extension: Durable Orchestration Client/Triggers aren't part of generated function.json in VS2017; execution fails

Created on 4 Jan 2018  路  5Comments  路  Source: Azure/azure-functions-durable-extension

When using the Visual Studio 2017 Functions Tools, creating an Azure Functions v2 Durable Function results in a failure at runtime due to a malformed function.json file which doesn't contain the correct binding information for the OrchestrationTrigger or OrchestrationClient objects in the function signature

Repro steps

Provide the steps required to reproduce the problem

  1. Create a new Azure Function v2 Project in VS2017.15.5.2 with Azure Functions and Web Jobs Tools v15.0.31201.0
  2. Select HTTPTrigger as the function type
  3. Update the Webjobs nuget package to v1.0.7
  4. Add the Microsoft.Azure.WebJobs.extensions.DurableTask v1.1.0-beta2 nuget package to the project
  5. Change the code for the Function created from step 2 to:
[FunctionName("Function1")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequestMessage req, [OrchestrationClient]DurableOrchestrationClient starter, TraceWriter log)
{
    return new HttpResponseMessage(HttpStatusCode.OK);
}
  1. Hit F5

Expected behavior

The Functions runtime executes in .Net Core (dotnet.exe) and gives me the URL to hit for the created Durable Function.

Actual behavior

Functions runtime spits out errors like:
~
[1/3/2018 11:21:16 PM] ScriptHost initialization failed
[1/3/2018 11:21:16 PM] System.Private.CoreLib: 'TriggerHandlesReturnValue' property specified was not found.
Listening on http://localhost:7071/
Hit CTRL-C to exit...
Object reference not set to an instance of an object.
~

Upon further investigation one can find the generated function.json file in bindebug\netstandard2.0\Function1 and see it's missing the binding for the OrchestratorClient object:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions.Generator-1.0.7",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "httpTrigger",
      "methods": [
        "post"
      ],
      "authLevel": "function",
      "name": "req"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/AzureFunctions.Durable.dll",
  "entryPoint": "AzureFunctions.Durable.Orchestrator.Run"
}

Changing the Function code to:

[FunctionName("Function1")]
public static void Run([OrchestrationTrigger]DurableOrchestrationClient starter, TraceWriter log)
{
    return;
}

will generate the exepected values in function.json of:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions.Generator-1.0.7",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "orchestrationTrigger",
      "name": "starter"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/FunctionApp1.dll",
  "entryPoint": "FunctionApp1.Function1.Run"
}

but the same errors occur during runtime.

external

Most helpful comment

This is related to Azure/Azure-Functions#625, where the Functions V2 CLI version is bound to the version of the VS Functions extension installed. A v2 HttpTrigger on SDK 1.0.7 works if you force the project to use the latest Functions V2 CLI by following the workaround I posted in that issue.

The second snippet of C# code needs to use DurableOrchestrationContext instead of DurableOrchestrationClient with the OrchestrationTrigger attribute.

All 5 comments

Thanks for opening this detailed issue. I'll follow up with the tooling team to see what might be going on.

Workaround

  • Microsoft.Azure.WebJobs.Extensions.DurableTask -> v1.0.0-beta
  • Microsoft.NET.Sdk.Functions -> v1.0.6

Be sure to do the downgrades in that order (due to dependencies).

Functions runtime executes project w/o issue in this state.

Edit: nevermind. Upon hitting the HttpTrigger function that has the OrchestrationClient attribute, the runtime now throws
~
[1/4/2018 6:32:06 PM] Executing 'Orchestrator' (Reason='This function was programmatically called via the host APIs.', Id=027cdd1f-e5eb-4351-b178-20d1a47e9364)
[1/4/2018 6:32:07 PM] A ScriptHost error has occurred
[1/4/2018 6:32:07 PM] Exception while executing function: Orchestrator. Autofac: The requested service 'System.Net.Http.Formatting.IContentNegotiator' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
~

Filed as #122

Using your setup, I was able to workaround the issue by simply downgrading the Microsoft.Azure.WebJobs.Extensions.DurableTask to v1.0.0-beta. It didn't matter which version of Microsoft.NET.Sdk.Functions I used. Note that I had to do a clean build in between tests because it seems not everything gets cleaned up properly between regular builds.

I think the root of the problem is that VS runs a particular version of the Functions CLI, and that CLI targets a specific version of the Functions runtime, which may be different from the version required by the extension. I used the _Modules_ window in Visual Studio to locate all the loaded assemblies and made this determination. The runtime assemblies are under %LOCALAPPDATA%\2.0.1-beta*. From what I can tell, these are the "3.0.0-beta3" versions of the WebJobs runtime (the latest Durable Functions release requires 3.0.0-beta4*).

If this is all true, then I think the proper fix is to have a new version of the CLI released which takes a dependency on the latest version of the Functions runtime bits. 1.0.7 is loading an older runtime.

related to your needing to do clean builds, I filed a bug for this longtime annoyance of mine w/ the VS 2017 extension here ;)

This is related to Azure/Azure-Functions#625, where the Functions V2 CLI version is bound to the version of the VS Functions extension installed. A v2 HttpTrigger on SDK 1.0.7 works if you force the project to use the latest Functions V2 CLI by following the workaround I posted in that issue.

The second snippet of C# code needs to use DurableOrchestrationContext instead of DurableOrchestrationClient with the OrchestrationTrigger attribute.

Was this page helpful?
0 / 5 - 0 ratings