我正在探索从Azure应用程序配置中获取配置数据的各种方法,并获得了大多数方法的工作,但是我正在努力在ASP上的Web API中实现Azure事件网格事件处理程序。NET Core 3.1。我想知道是否有可能通过事件网格通知Web API有关更改,而不是在Azure应用程序配置的缓存设置过期时进行轮询。一旦收到通知,配置值应该更新,当有人向Web API发出请求时,新值应该提供给任何控制器。
我已经在我的Program.cs、Startup.cs、服务总线消费者中包含了内容,我在其中设置了事件网格订阅者和示例控制器。
从我从微软的文档中读到的,我的理解是iconfigationrefresher。ProcessPushNotification方法将缓存过期时间重置为一个短的随机延迟,而不是CreateHostedBuilder方法中设置的缓存过期时间,当调用iconconfigurationrefresher . tryrefreshasync()时,它会更新配置值。
我遇到的问题是无法将iconconfigurationrefresher的具体类的实例注入到RegisterRefreshEventHandler方法中,然后调用ProcessPushNotification来重置过期时间。
我也可能是错误的,因为我假设在控制台应用程序中工作的RegisterRefreshEventHandler代码也将适用于Web API。请让我知道我的方法是否有效?
Program.cs
public class Program
{
private static IConfiguration _configuration;
private static IConfigurationRefresher _refresher;
public static void Main(string[] args)
{
_configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: false).Build();
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.ConfigureAppConfiguration((hostingContext, config) =>
{
var settings = config.Build();
config.AddAzureAppConfiguration(options =>
{
options
.Connect(_configuration["AppConfig"]).ConfigureRefresh(
refresh => refresh.Register(key: "Api:Sentinel", refreshAll: true).SetCacheExpiration(TimeSpan.FromDays(1))
).Select(KeyFilter.Any, "ClientA");
_refresher = options.GetRefresher();
}
);
}).UseStartup<Startup>());
}
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration, IConfigurationRefresher configurationRefresher)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<TFASettings>(Configuration.GetSection("Api:TFA"));
services.AddControllers();
services.AddAzureAppConfiguration();
services.AddSingleton<IServiceBusConsumer, ServiceBusConsumer>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
var bus = app.ApplicationServices.GetRequiredService<IServiceBusConsumer>();
bus.RegisterRefreshEventHandler();
app.UseAzureAppConfiguration();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
ServiceBusConsumer.cs
public class ServiceBusConsumer : IServiceBusConsumer
{
public IConfigurationRefresher configurationRefresher;
public ServiceBusConsumer()
{
}
public void RegisterRefreshEventHandler()
{
SubscriptionClient serviceBusClient = new SubscriptionClient("*****", "*****", "*****");
serviceBusClient.RegisterMessageHandler(
handler: (message, cancellationToken) =>
{
// Build EventGridEvent from notification message
EventGridEvent eventGridEvent = EventGridEvent.Parse(BinaryData.FromBytes(message.Body));
// Create PushNotification from eventGridEvent
eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification);
//// Prompt Configuration Refresh based on the PushNotification
//configurationRefresher.ProcessPushNotification(pushNotification);
return Task.CompletedTask;
},
exceptionReceivedHandler: (exceptionargs) =>
{
Console.WriteLine($"{exceptionargs.Exception}");
return Task.CompletedTask;
});
}
}
样品控制器
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly TFASettings _tfaSettings;
public WeatherForecastController(IOptionsSnapshot<TFASettings> tfaSettings)
{
_tfaSettings = tfaSettings.Value;
}
[HttpGet]
public WeatherForecast Get()
{
return new WeatherForecast
{
AuthenticationText = _tfaSettings.AuthenticationWording
};
}
}
您可以通过依赖注入获得IConfigurationRefresher
的具体实例。您甚至还可以从构造函数中调用RegisterRefreshEventHandler()
。您的ServiceBusConsumer.cs
可以看起来像这样。
private IConfigurationRefresher _configurationRefresher;
public ServiceBusConsumer(IConfigurationRefresherProvider refresherProvider)
{
_configurationRefresher = refresherProvider.Refreshers.FirstOrDefault();
RegisterRefreshEventHandler();
}