升级 Azure Function .Net 8 后 - 如何处理 Startup.cs 中的依赖注入?无法调试HTTP功能

问题描述 投票:0回答:1

升级 Azure Function .Net 8 后无法调试代码

请在下面找到我的 Program.cs 和 Startup.cs。 我读了文档,它说在 dotnet 隔离模型中,不需要 starup.cs。无法理解那么我该如何处理我的依赖注入。

这是我的Program.cs

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(services =>
{
    services.AddApplicationInsightsTelemetryWorkerService();
    services.ConfigureFunctionsApplicationInsights();
})
.ConfigureFunctionsWebApplication()
.Build();


 host.Run();

这是我的 Startup.cs 文件

class Startup : FunctionsStartup
{
 
 private IConfiguration _configuration;

 public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
 {

     var cred = new ClientSecretCredential(Settings.TenantId, Settings.ClientId, Settings.ClientSecret);

     if (!string.IsNullOrEmpty(Settings.SecondaryAppConfigConnection))
     {
         builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
         {
             options.Connect(Settings.SecondaryAppConfigConnection)
              .ConfigureKeyVault(kv => kv.SetCredential(cred))
              .Select(KeyFilter.Any, LabelFilter.Null)
             .Select(KeyFilter.Any, Settings.Environment);
         }, true).AddAzureAppConfiguration(options =>
         {
             options.Connect(Settings.AppConfigConnection)
              .ConfigureKeyVault(kv => kv.SetCredential(cred))
              .Select(KeyFilter.Any, LabelFilter.Null)
             .Select(KeyFilter.Any, Settings.Environment);
         }, true);
     }
     else
     {

         builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
         {
             options.Connect(Settings.AppConfigConnection)
                 .ConfigureKeyVault(kv => kv.SetCredential(cred))
                 .Select(KeyFilter.Any, LabelFilter.Null)
                .Select(KeyFilter.Any, Settings.Environment);
         });
     }

     _configuration = builder.ConfigurationBuilder.Build();
     
 }

 public override void Configure(IFunctionsHostBuilder builder)
 {
     var settings = new GatewayFunctionSettingProvider(_configuration);
     var connectionString = settings.GetConnectionString();

     Endpoint.Utilities.Logging.LoggerHelpers.ConfigureSerilogForAzureFunctions(settings);

     builder.Services.AddAzureAppConfiguration();
     builder.Services.AddScoped<ICacheDataAdapter>(s => new RedisCacheDataAdapter(_configuration["RedisHost"]));
     builder.Services.AddSingleton<ICertificateManager>(s => new CertificateManager(settings, new RedisCacheDataAdapter(_configuration["RedisHost"]))); 
     builder.Services.AddSingleton<IMassTransitRequest<MonitorUserIdPoolRequest>>(s => new MassTransitRequest<MonitorUserIdPoolRequest>());
     builder.Services.AddSingleton(s => settings);
     builder.Services.AddSingleton<CoreSettingsProvider>(s => settings);
     builder.Services.AddSingleton<SettingsProvider>(s => settings);
     builder.Services.AddSingleton<IConnectionMultiplexer>(s => ConnectionMultiplexer.Connect(settings.RedisHost));
     builder.Services.AddScoped<IHiLoDataAdapter>(s => new HiLoDataAdapter(connectionString, settings.UserIdHiLoCapacity));
     builder.Services.AddScoped<IUserIdGenerationService, UserIdGenerationService>();
     builder.Services.AddMassTransitForAzureFunctions(cfg =>{}, "AzureWebJobsServiceBus");
     builder.Services.AddSingleton(Bus.Factory.CreateUsingAzureServiceBus(x => x.Host(settings.AzureWebJobsServiceBus)));
     builder.Services.AddLogging();
     builder.Services.AddSingleton(x => new BlobServiceClient(connectionString));
     builder.Services.AddFunctionsWorkerDefaults();
     SettingsProvider.RegisterCurrentProvider(() => settings);
 }

}

本地设置.json

{
     "IsEncrypted": false,
   "Values": {

        "FUNCTIONS_EXTENSION_VERSION": "~4",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",

       }
   }

enter image description here

主机.json

{
   "version": "2.0",
    "logging": {
        "applicationInsights": {
              "samplingSettings": {
                       "isEnabled": true,
                       "excludedTypes": "Request"
           }
          }
         },
         "functionTimeout": "00:30:00"
       }

这里是具有HTTP和定时器功能的函数代码

     public class EmailAlertOnPasswordExpiration
     {
        private readonly ISendEndpointProvider sendEndpointProvider;
        private GatewayFunctionSettingProvider settings;
 

            public EmailAlertOnPasswordExpiration(ISendEndpointProvider SendEndpointProvider, 
             GatewayFunctionSettingProvider settings)
        {
             this.sendEndpointProvider = SendEndpointProvider;
             this.settings = settings;

         }
         [Function("EmailAlertOnPasswordExpiration")]
         public async Task Run([TimerTrigger("%EmailAlertOnPasswordExpirationTrigger%")] 
         TimerInfo myTimer, ILogger log)
         {
            log.LogInformation($"EmailAlertOnPasswordExpire Timer trigger function executed 
            at: {DateTime.Now}");
       await PasswordExpiryUserList(log);
   }

   [Function("EmailAlertOnPasswordExpirationGet")]
   public async Task<IActionResult> EmailAlertOnPasswordExpirationGet(
      [HttpTrigger(AuthorizationLevel.Function, "get", Route = "Email-Alert")] HttpRequest req,
      ILogger log)
   {
       log.LogInformation($"EmailAlertOnPasswordExpire GET trigger function executed at: {DateTime.Now}");
       await PasswordExpiryUserList(log);

       return new OkObjectResult("OK");

   }
   public async Task PasswordExpiryUserList(ILogger log)
   {
       var nodeNameProvider = new NodeNameProvider(settings.GetConnectionString());
       var nodes = nodeNameProvider.GetNodes();

       string query = "select u.UserName,u.FirstName, u.LastName,u.Id from [dbo].[Credential] c inner join dbo.[User] u  on c.UserId = u.Id WHERE  CONVERT(date, c.ExpiresOn) = CONVERT(DATE, DATEADD(day, 7, getdate())) and u.Active = 1 ";

       using (SqlConnection connection = new SqlConnection(settings.GetConnectionString()))
       {
           connection.Open();

           DataTable table = new DataTable();
           using (var da = new SqlDataAdapter(query, connection))
           {
               da.Fill(table);
               if (table.Rows.Count > 0)
               {
                   log.LogInformation($"After execute query table has " + table.Rows.Count + " rows");

               List<Endpoint.Contracts.UserData> userList = new List<Endpoint.Contracts.UserData>();
               userList = (from DataRow dr in table.Rows
                           select new Endpoint.Contracts.UserData()
                           {
                               UserName = dr["UserName"].ToString(),
                               FirstName = dr["FirstName"].ToString(),
                               LastName = dr["LastName"].ToString(),
                               UserId = dr["Id"].ToString()

                               }).ToList();

                   UserDataMessage userMessage = new UserDataMessage
                   {
                       UserInfoData = userList
                   };
                   if (userMessage != null | userMessage.UserInfoData.Count > 0)
                   {
                       log.LogInformation($"UserList count is" + userMessage.UserInfoData.Count);
                       foreach (var nodeName in nodes)
                       {
                           try
                           {
                               var uri = new Uri($"queue:NodeWorker-{nodeName}");
                               var endpoint = await sendEndpointProvider.GetSendEndpoint(uri);
                               await endpoint.Send(userMessage, ctx =>
                                   {
                                       ctx.TimeToLive = TimeSpan.FromMinutes(1);
                                   });
                           }
                           catch (Exception ex)
                           {
                               log.LogInformation($"Error posting Password Expiry Email Alert info to {nodeName}", ex);
                           }
                       }
                   }
                   else
                   {
                       log.LogInformation($"UserList is null");
                   }
               }
               else
               {
                   log.LogInformation($"DataTable is null");
               }
           }
       }
   }

}

请指导我如何调试代码?没有收到错误。当我运行 HTTP 函数时

enter image description here

azure azure-functions azure-web-app-service .net-8.0
1个回答
0
投票

因此,dotnet 隔离模型中的变化是,这些函数现在在隔离的容器中运行,其中 HostBuilder 函数定义了您将要使用的大部分依赖项以及其他与主机相关的配置。我也必须不断尝试和犯错才能使其正常工作,但总而言之,在 Program.cs 中:

var host = HostBuilder()
    .ConfigureFunctionWorkerDefaults()
    .ConfigureServices((hostContext, services) => 
    {
        // Put your dependency injections here, for example
        var keyVaultUrl = new Uri(Environment.GetEnvironmentVariable("ConnectionURL")!);
        services.AddAzureClients(clientBuilder => 
        {
            clientBuilder.UseCredentials(new DefaultAzureCredential());
            clientBuilder.AddSecretClient(keyVault);
        }
    })

您现在设置了一个天蓝色的秘密客户端依赖项,将其注入到一个函数中(例如 HTTP 触发器),转到函数类并将依赖项添加到您的类构造函数中,在您的示例中:

public EmailAlertOnPasswordExpiration(... , SecretClient secretClient)
{
    // Use the secret client as an injected dependency
}

现在调试有点困难,因为您需要设置本地开发环境才能访问此资源,或者在 local-settings.json 中创建本地设置以获得一些虚拟数据或与虚拟 Azure 的连接资源(我希望我明白了问题的要点)。

© www.soinside.com 2019 - 2024. All rights reserved.