简体   繁体   中英

Azure webjob using .NET core 3.1

I am writing a azure webjob using .net core 3.1 and I am getting the following runtime exception: InvalidOperationException: %EventHubName% does not resolve to a value.

where my trigger looks like: ProcessEvent([EventHubTrigger("%EventHubName%", ConsumerGroup = "%ConsumerGroupName%")] EventData eventData)

I have registered the configuration in program.cs

I have added appSettings.environment.json file which contains something like:

"EventHubConfig": { "EventHubConnectionString": "..", "EventHubName": "..", "EventProcessorHostName": "..", "ConsumerGroupName": "..", "StorageConnectionString": "..", "StorageContainerName": ".." },

Can anyone suggest what I maybe missing?

Using %%XXX%% is the correct way to read settings.

When you are developing locally your app search for those variable in the local.settings.json file.

Example:

{
    "EventHubName": "myeventhubname"
}

If you deployed on Azure you need to add variables to the Applications Settings Read more

Update 0515:

The workaround:

1.Please add both appsettings.json and appsettings.dev.json (Remember right click these files -> select properties -> set "Copy to Output Directory" as "copy if newer") files into your project. The 2 json files should have the same structure(the keys), but the value can be different. Like below:

My appsettings.json file:

{
  "AzureWebJobsStorage": "xxxxx",
  "EventHubConnectionString": "xxxx",
  "EventHubName": "yyeventhub1",
  "ConsumerGroupName": "cg1"
}

My appsettings.dev.json file:

   {
      "AzureWebJobsStorage": "xxxxx",
      "EventHubConnectionString": "xxxx",
      "EventHubName": "yyeventhub2",
      "ConsumerGroupName": "hub2cg"
    }

2.In CustomNameResolver class, use the code below:

public class CustomNameResolver : INameResolver
{
    public string Resolve(string name)
    {
        var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile("appsettings.dev.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables()
        .Build();

        return config[name];
    }
}

note , appsettings.json should be added before appsettings.dev.json, so the settings in appsettings.dev.json has high priority which will overwrite the same keys in appsettings.json.

3.Then run the project and send events to yyeventhub2 which is defined in appsettings.dev.json, then you can find the webjob is triggered.


Original answer:

There're some limitations when use %% in the function.

As per my test, here are some notes:

1.Some latest nuget packages cannot work with eventhub trigger, you should use the below version of nuget packages:

<ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="3.0.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.EventHubs" Version="4.1.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.10" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.4" />
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
  </ItemGroup>

2.The eventhub namespace connection string cannot be used in this format %EventHubConnectionString% in the Functions.cs.

3.Don't use the nested settings in appsettings.json.

4.Don't specify EventProcessorHostName and StorageContainerName in appsettings.json. The webjobs SDK automatically set them for you.

5.When use %% format, you should use Custom binding expressions to resolve the name.

The following are my code and appsettings.json:

appsettings.json (please also right click this file -> select Properties -> set "Copy to Output Directory" as "Copy if newer"):

{     
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=xx;AccountKey=xx;BlobEndpoint=https://xxx.blob.core.windows.net/;TableEndpoint=https://xxx.table.core.windows.net/;QueueEndpoint=https://xxx.queue.core.windows.net/;FileEndpoint=https://xxx.file.core.windows.net/",
    "EventHubConnectionString": "Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxx",
    "EventHubName": "xxx",
    "ConsumerGroupName": "xxx"  
}

My NameResolver class(create a custom class named CustomNameResolver.cs) :

public class CustomNameResolver : INameResolver
{
    public string Resolve(string name)
    {
        var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        //.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables()
        .Build();

        return config[name];
    }
}

Program.cs:

class Program
{     

    static void Main(string[] args)
    {
        var builder = new HostBuilder();
        var resolver = new CustomNameResolver();

        builder.ConfigureWebJobs(b =>
        {
            b.AddAzureStorageCoreServices();
            b.AddAzureStorage();
            b.AddEventHubs();
        });
        builder.ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        });          

        builder.ConfigureServices(s => s.AddSingleton<INameResolver>(resolver));

        var host = builder.Build();
        using (host)
        {
            host.Run();
        }
    }
}

Functions.cs:

public class Functions
{
    public static void ProcessEvent([EventHubTrigger("%EventHubName%", Connection = "EventHubConnectionString",ConsumerGroup = "%ConsumerGroupName%")] EventData eventData, ILogger logger)
    {
        logger.LogInformation("it is triggered!" + DateTime.Now.ToLongTimeString());
    }
}

Test result:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM