迁移到 Net5 后找不到带有 ServiceBusTrigger 的函数

Function with ServiceBusTrigger not found after migration to Net5

我已经阅读了几本关于这个主题的指南,但都没有成功。 以下指南给了我很多关于设置的提示,我根本无法理解也无法在官方文档中找到这些提示:

https://codetraveler.io/2021/05/28/creating-azure-functions-using-net-5/

但我仍在努力寻找一些作品来制作它 运行。

这是我在本地 运行 时收到的消息:

No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.). For detailed output, run func with --verbose flag.

此消息包含我怀疑丢失但我不知道如何解决的内容:ServiceBus 部分。我不确定函数是否有足够的信息来连接到 ServiceBus。它在配置文件中,但我不知道函数在哪里知道要使用配置的哪一部分。

这是我的功能:

public class MyFunction
{
    private readonly IService1 service;

    public MyFunction(IService1 service)
    {
        this.service = service;
    }

    [FunctionName("Function1")]
    public async Task ProcessMessage([ServiceBusTrigger("topic", "subscription", Connection = "ServiceBusConnectionString")] Message message)
    {
        await service.Process(message);
    }
}

这是我的 appsettings.json 配置文件:

{
  "ConnectionStrings": {
    "ServiceBusConnectionString": "Endpoint=sb://****.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=******"
  }
}

一些local.settings.json(我猜这使得在本地机器上运行成为可能)

{
  "IsEncrypted": false,
  "AzureWebJobsStorage": "UseDevelopmentStorage=true",
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

程序class:

public class Program
{
    public static Task Main(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true)
            .Build();

        var builder = new HostBuilder()
            .ConfigureFunctionsWorkerDefaults()
            .ConfigureServices((context, services) =>
            {
                services.AddTransient<IService1, service>();
            });
        
        var host = builder.Build();
        return host.RunAsync();
    }
}

我还修改了项目文件以包含:

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
  </PropertyGroup>

并且:

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

还添加了几个 Nuget 包:

<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="4.2.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.4" OutputItemType="Analyzer" />

哦天啊...这是一个巨大的设置!我希望未来的版本能让它变得更容易!!!

查看您的函数代码,我有根据地猜测您正在混合进程内和进程外代码。

解决这个问题。按照以下步骤操作。

  1. process/isolated 流程模型不应使用任何对 Microsoft.Azure.WebJobs.* 包的引用,例如 Microsoft.Azure.WebJobs.Extensions.ServiceBus。相反,您应该引用 Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 包。

  2. 使用 Function 属性而不是 FunctionName 属性。 FunctionName 来自 Microsoft.Azure.WebJobs 我们不应该在 process/isolated 流程功能应用程序中使用它。

您的函数代码在更改后将如下所示。

public class MyFunction
{
    private readonly IService1 service;
    private readonly ILogger<MyFunction> logger;

    public MyFunction(IService1 service, ILogger<MyFunction> logger)
    {
        this.service = service ?? throw new ArgumentNullException(nameof(service));
        this.logger = logger?? throw new ArgumentNullException(nameof(logger));
    }

    [Function("Function1")]
    public async Task ProcessMessage([ServiceBusTrigger("mytopic",
        "mysubscription", 
        Connection = "ServiceBusConnectionString")] object message)
    {
        logger.LogInformation($"ServiceBus OOP function processed: {message}");
        await service.Process(message);
    }
}

ServiceBusTrigger 属性的 Connection 属性 值是您的应用程序设置条目的名称,用于指定服务总线连接字符串。对于本地 运行ning,您应该将其保存在 local.settings.json 文件中的 Values 部分内。您可以添加一个新条目(在您现有的 FUNCTIONS_WORKER_RUNTIME 条目 之后),如下所示。

{
  "Values": {
    "ServiceBusConnectionString": "PutYourServiceBusConnStringHere"
  }
} 

当您必须 运行 在产品中执行此操作时,您将转到您的函数应用程序资源并在 设置 -> 配置 下添加一个新的应用程序设置条目。设置条目的名称将为 ServiceBusConnectionString。函数 运行 时间将读取此值并使用该值。

我强烈建议您在 Visual studio 和 select 隔离流程模型和服务总线触发器中创建一个新的“azure functions”项目。这将为您创建一个新项目,其中包含工作服务总线触发器所需的所有最少部分。