{"id":95974,"date":"2019-07-01T17:01:11","date_gmt":"2019-07-01T17:01:11","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/aspnet\/?p=22289"},"modified":"2019-07-01T17:01:11","modified_gmt":"2019-07-01T17:01:11","slug":"configuring-a-server-side-blazor-app-with-azure-app-configuration","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2019\/07\/01\/configuring-a-server-side-blazor-app-with-azure-app-configuration\/","title":{"rendered":"Configuring a Server-side Blazor app with Azure App Configuration"},"content":{"rendered":"<div class=\"row justify-content-center\">\n<div class=\"col-md-4\">\n<div><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration.jpg\" width=\"58\" height=\"58\" alt=\"Avatar\" class=\"avatar avatar-58 wp-user-avatar wp-user-avatar-58 photo avatar-default\"><\/div>\n<\/div>\n<\/div>\n<div class=\"entry-meta\">\n<p>July 1st, 2019<\/p>\n<\/p><\/div>\n<p><!-- .entry-meta --> <\/p>\n<p>With <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-6\/\">.NET Core 3.0 Preview 6<\/a>, we added authentication &amp; authorization support to server-side Blazor apps. It only takes a matter of seconds to wire up an app to Azure Active Directory with support for single or multiple organizations. Once the project is created, it contains all the configuration elements in its <code>appsettings.json<\/code> to function. This is great, but in a team environment \u2013 or in a distributed topology \u2013 configuration files lead to all sorts of problems. In this post, we\u2019ll take a look at how we can extract those configuration values out of JSON files and into an Azure App Configuration instance, where they can be used by other teammates or apps.<\/p>\n<h2>Setting up Multi-org Authentication<\/h2>\n<p>In the <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-6\/\">.NET Core 3.0 Preview 6 blog post<\/a> we explored how to use the <strong>Individual User Accounts<\/strong> option in the authentication dialog to set up a Blazor app with ASP.NET Identity, so we won\u2019t go into too much detail. Essentially, you click the <strong>Change<\/strong> link during project creation.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration.png\" alt=\"Click Change Auth during project creation\"><\/p>\n<p>In this example I\u2019ll be using an Azure Active Directory application to allow <em>anyone<\/em> with a Microsoft account to log into the app, so I\u2019ll select <strong>Work or School Accounts<\/strong> and then select <strong>Cloud \u2013 Multiple Organizations<\/strong> in the Change Authentication dialog.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-1.png\" alt=\"The Visual Studio add authentication dialog.\"><\/p>\n<p>Once the project is created, my <code>AzureAD<\/code> configuration node contains the 3 key pieces of information my app\u2019s code will need to authenticate against Azure Active Directory; my tenant URL, the client ID for the AAD app Visual Studio created for me during the project\u2019s creation, and the callback URI so users can get back to my app once they\u2019ve authenticated.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-2.png\" alt=\"The appsettings.json inclusive of the settings.\"><\/p>\n<p>Whilst this is conveniently placed here in my <code>appsettings.json<\/code> file, it\u2019d be more convenient if I didn\u2019t need any local configuration files. Having a centralized configuration-management solution would be easier to manage, as well as give me the ability to keep my config out of source control, should there come a point when things like connection strings need to be shared amongst developers.<\/p>\n<h2>Azure App Configuration<\/h2>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-app-configuration\/overview\">Azure App Configuration<\/a> is a cloud-based solution for managing all of your configuration values. Once I have an Azure App Configuration instance set up in my subscription, adding the configuration settings is simple. By default, they\u2019re hidden from view, but I can click <strong>Show Values<\/strong> or select an individual setting for editing or viewing.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-3.png\" alt=\"The config values in Azure App Configuration\"><\/p>\n<h3>Convenient .NET Core IConfiguration Integration<\/h3>\n<p>The Azure App Configuration team has shipped a NuGet package containing extensions to ASP.NET and .NET Core that enable developers the ability of using the service, but without needing to change all your code that already makes use of <code>IConfiguration<\/code>. To start with, install the <code>Microsoft.Extensions.Configuration.AzureAppConfiguration<\/code> <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Extensions.Configuration.AzureAppConfiguration\/1.0.0-preview-008920001-990\">NuGet package<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-4.png\" alt=\"Adding the NuGet Package for Azure App Configuration\"><\/p>\n<p>You\u2019ll need to copy the connection string from the Azure Portal to enable connectivity between your app and Azure App Configuration.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-5.png\" alt=\"Copying the Azure App Configuration connection string\"><\/p>\n<p>Once that value has been copied, you can use it with either <code>dotnet user-secrets<\/code> to configure your app, or using a debug-time environment variable. Though it seems like we\u2019ve created yet one more configuration value to track, think about it this way: this is the <strong>only<\/strong> value you\u2019ll have to set using an environment variable; all your other configuration can be set via Azure App Configuration in the portal.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-6.png\" alt=\"Setting up the Azure App Configuration connection string in an environment variable\"><\/p>\n<h3>Using the Azure App Configuration Provider for .NET Core<\/h3>\n<p>Once the NuGet package is installed, the code to instruct my .NET Core code to use Azure App Configuration whenever it reads any configuration values from <code>IConfiguration<\/code> is simple. In <code>Program.cs<\/code> I\u2019ll call the <code>ConfigureAppConfiguration<\/code> middleware method, then use the <code>AddAzureAppConfiguration<\/code> extension method to get the connection string from my <code>ASPNETCORE_AzureAppConfigConnectionString<\/code> environment variable. If the environment variable isn\u2019t set, the call will noop and the other configuration providers will do the work.<\/p>\n<p>This is <strong>great<\/strong>, because I won\u2019t even need to change existing \u2013 or in this case, template-generated code \u2013 I just tell my app to use Azure App Configuration and I\u2019m off to the races. The full update to <code>Program.cs<\/code> is shown below.<\/p>\n<pre><code class=\"csharp\">\/\/ using Microsoft.Extensions.Configuration.AzureAppConfiguration; public static IHostBuilder CreateHostBuilder(string[] args) =&gt; Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) =&gt; { config.AddAzureAppConfiguration(options =&gt; { var azureAppConfigConnectionString = hostingContext.Configuration[\"AzureAppConfigConnectionString\"]; options.Connect(azureAppConfigConnectionString); }); }) .ConfigureWebHostDefaults(webBuilder =&gt; { webBuilder.UseStartup&lt;Startup&gt;(); });\n<\/code><\/pre>\n<p>When I run the app, it first reaches out to Azure App Configuration to get all the settings it needs to run and then works as if it were configured locally using <code>appsettings.json<\/code>. As long as my teammates or other services needing these values have the connection string to the Azure App Configuration instance holding the settings for the app, they\u2019re good.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-7.png\" alt=\"Running the authenticated app\"><\/p>\n<p>Now, I can remove the configuration values entirely from the <code>appsettings.json<\/code> file. If I want to control the logging behavior using Azure App Configuration, I could move these left-over settings out, too. Even though I\u2019ll be using Azure App Configuration as, the other providers are still there.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-8.png\" alt=\"The appsettings.json with the settings removed.\"><\/p>\n<h2>Dynamic Re-loading<\/h2>\n<p>Log levels are a good example of how the Azure App Configuration service can enable dynamic reloading of configuration settings you might need to tweak frequently. By moving my logging configuration into Azure App Configuration, I can change the log level right in the portal. In <code>Program.cs<\/code>, I can use the <code>Watch<\/code> method to specify which configuration settings I\u2019ll want to reload when they change.<\/p>\n<pre><code class=\"csharp\">public static IHostBuilder CreateHostBuilder(string[] args) =&gt; Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) =&gt; { config.AddAzureAppConfiguration(options =&gt; { var azureAppConfigConnectionString = hostingContext.Configuration[\"AzureAppConfigConnectionString\"]; options.Connect(azureAppConfigConnectionString) .Watch(\"Logging:LogLevel:Default\") .Watch(\"Logging:LogLevel:Microsoft\") .Watch(\"Logging:LogLevel:Microsoft.Hosting.Lifetime\"); }); }) .ConfigureWebHostDefaults(webBuilder =&gt; { webBuilder.UseStartup&lt;Startup&gt;(); });\n<\/code><\/pre>\n<p>The default load-time is 30 seconds, but now, should I need to turn up the volume on my logs to get a better view of what\u2019s happening in my site, I don\u2019t need to re-deploy or even stop my site. Simply changing the values in the portal will be enough \u2013 30 seconds later the values will be re-loaded from Azure App Configuration and my logging will be more verbose.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-9.png\" alt=\"Changing configuration values in the portal\"><\/p>\n<h3>Configuration Source Ordering<\/h3>\n<p>The <code>JsonConfigurationSource<\/code> configuration sources \u2013 those which load settings from <code>appsettings.json<\/code> and <code>appsettings.{Environment}.json<\/code> \u2013 are loaded during the call to <code>CreateDefaultBuilder<\/code>. So, by the time I call <code>AddAzureAppConfiguration<\/code> to load in the <code>AzureAppConfigurationSource<\/code>, the JSON file providers are already in the configuration sources list.<\/p>\n<p>The importance of ordering is evident here; should I want to override the configuration values coming from Azure App Configuration with my local <code>appsettings.json<\/code> or <code>appsettings.Development.json<\/code> files, I\u2019d need to re-order the providers in the call to <code>ConfigureAppConfiguration<\/code>. Otherwise, the JSON file values will be loaded first, then the last source (the one that will \u201cwin\u201d) will be the Azure App Configuration source.<\/p>\n<h2>Try it Out<\/h2>\n<p>Any multi-node or microservice-based application topology benefits from centralized configuration, and teams benefit from it by not having to keep track of so many configuration settings, environment variables, and so on. Take a look over the Azure App Configuration documentation. You\u2019ll see that there are a multitude of other features, like Feature Flags and dark deployment support. Then, create an instance and try wiring your existing ASP.NET Code up to read configuration values from the cloud.<\/p>\n<div class=\"authorinfoarea\">\n<div><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/07\/configuring-a-server-side-blazor-app-with-azure-app-configuration-1.jpg\" width=\"96\" height=\"96\" alt=\"Avatar\" class=\"avatar avatar-96 wp-user-avatar wp-user-avatar-96 photo avatar-default\"><\/div>\n<div>\n<h5><a class=\"no-underline\" aria-label=\" Brady Gaster\" target=\"_blank\" href=\"https:\/\/devblogs.microsoft.com\/aspnet\/author\/bradygmicrosoft-com\/\" rel=\"noopener noreferrer\"> Brady Gaster<\/a><\/h5>\n<p>Senior Program Manager,&nbsp;ASP.NET Core<\/p>\n<p><strong>Follow <\/strong>&nbsp;&nbsp;&nbsp;<a class=\"no-underline stayinformed\" aria-label=\" Brady Gaster Twitter profile\" target=\"_blank\" href=\"https:\/\/twitter.com\/bradygaster\" rel=\"noopener noreferrer\"><i class=\"fa fa-twitter\"><\/i><\/a><a class=\"no-underline stayinformed\" aria-label=\" Brady Gaster GitHub profile\" target=\"_blank\" href=\"https:\/\/github.com\/bradygaster\" rel=\"noopener noreferrer\"><i class=\"fa fa-github\"><\/i><\/a><a class=\"no-underline stayinformed hvr-pop\" aria-label=\" Brady Gaster RSS Feed\" target=\"_blank\" href=\"https:\/\/devblogs.microsoft.com\/aspnet\/author\/bradygmicrosoft-com\/feed\/\" rel=\"noopener noreferrer\"><\/a><\/p>\n<\/p><\/div>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>July 1st, 2019 With .NET Core 3.0 Preview 6, we added authentication &amp; authorization support to server-side Blazor apps. It only takes a matter of seconds to wire up an app to Azure Active Directory with support for single or multiple organizations. Once the project is created, it contains all the configuration elements in its [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":95975,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[67,54,120],"class_list":["post-95974","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-webdev","tag-aspnetcore","tag-azure","tag-blazor"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/95974","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=95974"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/95974\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/95975"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=95974"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=95974"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=95974"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}