Cosa sto cercando di fare: sto tentando di configurare la Configurazione app di Azure con un'applicazione Web mvc 2.1 core .net con una chiave sentinella nella Configurazione app di Azure, con l'obiettivo di poter cambiare le chiavi in azzurro e nessuna delle chiavi verrà aggiornato nelle mie app fino a quando il valore della sentinella non verrà modificato. In teoria, ciò dovrebbe consentirmi di configurare in modo sicuro hot swap.
Qual è il mio problema: quando lo faccio, non esiste alcun metodo WatchAndReloadAll () disponibile per guardare la sentinella su IWebHostBuilder e i metodi alternativi Refresh () non sembrano aggiornare la configurazione mentre affermano.
Informazioni di base e cosa ho provato: ho partecipato a VS Live - San Diego, la scorsa settimana e ho visto una demo sulla configurazione dell'app di Azure. Ho avuto dei problemi nel tentativo di ottenere l'applicazione per aggiornare i valori di configurazione durante l'implementazione, quindi ho anche fatto riferimento a questa demo descrivendo come fare anche questo. La sezione pertinente è di circa 10 minuti. Tuttavia, tale metodo non sembra essere disponibile su IWebHostBuilder.
Documentazione a cui mi riferisco: nella documentazione ufficiale non vi è alcun riferimento a questo metodo, consultare doc quickstart .net core e doc dynamic configuration .net core
Il mio ambiente: utilizzo di dot net core 2.1 eseguito da Visual Studio Enterprise 2019, con l'ultimo pacchetto nuget di anteprima per Microsoft.Azure.AppConfiguration.AspNetCore 2.0.0-preview-010060003-1250
Il mio codice: nella demo, hanno creato un IWebHostBuilder tramite il metodo CreateWebHostBuilder (string [] args) in questo modo:
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
var settings = config.Build();
config.AddAzureAppConfiguration(options =>
{
options.Connect(settings["ConnectionStrings:AzureConfiguration"])
.Use(keyFilter: "TestApp:*")
.WatchAndReloadAll(key: "TestApp:Sentinel", pollInterval: TimeSpan.FromSeconds(5));
});
})
.UseStartup<Startup>();
}
Ho anche provato in questo modo, utilizzando la documentazione corrente:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
var settings = config.Build();
config.AddAzureAppConfiguration(options =>
{
// fetch connection string from local config. Could use KeyVault, or Secrets as well.
options.Connect(settings["ConnectionStrings:AzureConfiguration"])
// filter configs so we are only searching against configs that meet this pattern
.Use(keyFilter: "WebApp:*")
.ConfigureRefresh(refreshOptions =>
{
// In theory, when this value changes, on the next refresh operation, the config will update all modified configs since it was last refreshed.
refreshOptions.Register("WebApp:Sentinel", true);
refreshOptions.Register("WebApp:Settings:BackgroundColor", false);
refreshOptions.Register("WebApp:Settings:FontColor", false);
refreshOptions.Register("WebApp:Settings:FontSize", false);
refreshOptions.Register("WebApp:Settings:Message", false);
});
});
})
.UseStartup<Startup>();
Quindi, nella mia classe di avvio:
public Startup(IConfiguration configuration)
{
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<Settings>(Configuration.GetSection("WebApp:Settings"));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseAzureAppConfiguration();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
e infine il mio modello di configurazione delle impostazioni:
public class Settings
{
public string BackgroundColor { get; set; }
public long FontSize { get; set; }
public string FontColor { get; set; }
public string Message { get; set; }
}
Ora, nel mio controller, tiro quelle impostazioni e le lancio in un sacchetto di visualizzazione per essere visualizzate sulla vista.
public class HomeController : Controller
{
private readonly Settings _Settings;
public HomeController(IOptionsSnapshot<Settings> settings)
{
_Settings = settings.Value;
}
public IActionResult Index()
{
ViewData["BackgroundColor"] = _Settings.BackgroundColor;
ViewData["FontSize"] = _Settings.FontSize;
ViewData["FontColor"] = _Settings.FontColor;
ViewData["Message"] = _Settings.Message;
return View();
}
}
Una vista semplice per visualizzare le modifiche:
<!DOCTYPE html>
<html lang="en">
<style>
body {
background-color: @ViewData["BackgroundColor"]
}
h1 {
color: @ViewData["FontColor"];
font-size: @ViewData["FontSize"];
}
</style>
<head>
<title>Index View</title>
</head>
<body>
<h1>@ViewData["Message"]</h1>
</body>
</html>
Posso ottenerlo per abbassare la configurazione la prima volta, tuttavia, la funzionalità di aggiornamento non sembra funzionare in alcun modo.
Nell'ultimo esempio, mi aspettavo che le configurazioni si aggiornassero quando la sentinella era impostata su qualsiasi nuovo valore, o almeno, per aggiornare un valore 30 secondi dopo che era stato modificato. Nessun intervallo di attesa aggiorna i valori e solo un arresto completo e un riavvio dell'app caricano la nuova configurazione.
Aggiornamento: aggiunta di app.UseAzureAppConfiguration (); nel metodo configure all'avvio e l'impostazione di un timeout esplicito nella cache per la configurazione ha risolto l'aggiornamento del metodo di aggiornamento dopo un determinato periodo di tempo, ma la funzionalità sentinel continua a non funzionare, né il flag updateAll sul metodo di aggiornamento.
ConfigureServices
metodo in startuop.cs, come services.Configure<LogSettings>(configuration.GetSection("LogSettings"));