How to get a complete list of CloudConfiguration from a web service at runtime?

The ConfigurationManager has a collection of AppSettings name values, but CloudConfigurationManager has only the GetSetting (string) method, where you can get 1 by 1 configuration settings if you know the key.

Is there a way to get the entire configuration of an executable role?

The main reason is because I want to make a strong typed configuration in order to distract it and make my code more verified. Using CloudConfigurationManager directly is an implicit dependency that I want to remove using an abstraction that I want to drown out in tests. Therefore, I find it practical. This brings me to my question.

I do not want to use a library like fx.configuration.azure because I have to carry my dependency at all, because it requires inheritance of the base class.

0
azure azure-web-roles
Jun 25 '15 at 12:28
source share
2 answers

AFAIK, there is no direct method that will provide you with this information.

However, there is a workaround that you can use. This includes the use of the Get Deployment service management API. This operation will return XML, and one of the elements will be Configuration , which contains your Base64 encoded service configuration file. You can read this element, convert it to a string, and parse the XML to go to the ConfigurationSettings elements. The child elements contain all the settings.

To do this, you can either write your own shell on top of the REST Service Management API, or use the Azure Management Library .

UPDATE

So, here is a sample code to list all the configuration options from the Service Configuration File using the Azure Management Library . This is a simple console application, hacked together in a very short period of time, thus, it has many opportunities for improvement :). For the management certificate, I used the data from the publish settings file.

You just need to install the Azure Management Library Nuget Package in the console application:

Microsoft.WindowsAzure.Management.Libraries installation package

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Management.Compute; using System.Security.Cryptography.X509Certificates; using System.Xml.Linq; namespace ReadConfigurationSettingsUsingAzureManagementLibrary { class Program { static string subscriptionId = "<subscription-id>"; static string managementCertContents = "<Base64 Encoded Management Certificate String from Publish Setting File>";//Certificate string from Azure Publish Settings file static string cloudServiceName = "<your cloud service name>"; static string ns = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"; static void Main(string[] args) { var managementCetificate = new X509Certificate2(Convert.FromBase64String(managementCertContents)); var credentials = new CertificateCloudCredentials(subscriptionId, managementCetificate); var computeManagementClient = new ComputeManagementClient(credentials); var response = computeManagementClient.HostedServices.GetDetailed(cloudServiceName); var deployment = response.Deployments.FirstOrDefault(d => d.DeploymentSlot == Microsoft.WindowsAzure.Management.Compute.Models.DeploymentSlot.Production); if (deployment != null) { var config = deployment.Configuration; XElement configXml = XElement.Parse(config); var roles = configXml.Descendants(XName.Get("Role", ns)); foreach (var role in roles) { Console.WriteLine(role.Attribute("name").Value); Console.WriteLine("-----------------------------"); var configurationSettings = role.Element(XName.Get("ConfigurationSettings", ns)); foreach (var element in configurationSettings.Elements(XName.Get("Setting", ns))) { var settingName = element.Attribute("name").Value; var settingValue = element.Attribute("value").Value; Console.WriteLine(string.Format("{0} = {1}", settingName, settingValue)); } Console.WriteLine("=========================================="); } } Console.ReadLine(); } } } 
+1
Jun 25 '15 at 15:48
source share

Here is an updated implementation that takes care that you work in the emulator or not, and if you work on the local web server or not. Once the dictionary returns, it can be easily distracted from the entire Castle.DictionaryAdapter application. I shared the code as a template project on GitHub here . Here is an excerpt:

 using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Xml; using System.Xml.Linq; using Castle.Components.DictionaryAdapter; using Core.Configuration.Interfaces; using Microsoft.Azure; using Microsoft.WindowsAzure.Management.Compute; using Microsoft.WindowsAzure.Management.Compute.Models; using Microsoft.WindowsAzure.ServiceRuntime; namespace Core.Configuration { public class AzureServiceConfigurationProvider : IAzureServiceConfigurationProvider { private readonly string _subscriptionId; // The Base64 Encoded Management Certificate string from Azure Publish Settings file // download from https://manage.windowsazure.com/publishsettings/index private readonly string _managementCertContents; private readonly string _cloudServiceName; private readonly string _serviceConfigurationNamespace; public DefaultAzureServiceConfigurationProvider(IWebConfigSettings webConfigSettings) { _subscriptionId = webConfigSettings.SubscriptionId; _managementCertContents = webConfigSettings.ManagementCertContents; _cloudServiceName = webConfigSettings.CloudServiceName; _serviceConfigurationNamespace = webConfigSettings.ServiceConfigurationNamespace; } public Dictionary<string, Dictionary<string, string>> GetConfigRaw() { Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigRaw->Start"); var configuration = new Dictionary<string, Dictionary<string, string>>(); var configXml = GetConfigXml(); Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigRaw->XmlExtracted"); var roles = configXml.Descendants(XName.Get("Role", _serviceConfigurationNamespace)); Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigRaw->Roles : "); foreach(var role in roles) { var roleConfiguration = new Dictionary<string, string>(); var roleName = role.Attribute("name").Value; Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigRaw->RoleName : " + roleName); var configurationSettings = role.Element(XName.Get("ConfigurationSettings", _serviceConfigurationNamespace)); if (configurationSettings == null) { throw new InvalidOperationException("configurationSettings is null"); } foreach(var element in configurationSettings.Elements(XName.Get("Setting", _serviceConfigurationNamespace))) { var settingName = element.Attribute("name").Value; var settingValue = element.Attribute("value").Value; Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigRaw->settingName : " + settingName + " settingValue : " + settingValue); roleConfiguration.Add(settingName, settingValue); } configuration.Add(roleName, roleConfiguration); } return configuration; } public IAzureServiceConfiguration GetConfig() { var configFactory = new DictionaryAdapterFactory(); IAzureServiceConfiguration config; try { var rawAzureServiceConfig = GetConfigRaw(); Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfig :"); var rawAzureWebServiceConfig = rawAzureServiceConfig["Core.Web"]; config = configFactory.GetAdapter<IAzureServiceConfiguration>(rawAzureWebServiceConfig); config = ComplementConfigurationFromConfigurationManager(config); } catch(Exception exception) { // happens in some projects when using Full Emulator // so we fallback to cloudconfigurationmanager // this is not bad since we have isolated it in configuration assembly Trace.WriteLine(exception.Message); Trace.WriteLine(exception.StackTrace); Hashtable hashConfig = GetConfigFromConfigurationManager(); config = configFactory.GetAdapter<IAzureServiceConfiguration>(hashConfig); } return config; } private IAzureServiceConfiguration ComplementConfigurationFromConfigurationManager(IAzureServiceConfiguration config) { Trace.WriteLine("Complementing configuration"); var azureConfigType = config.GetType(); foreach(PropertyInfo property in config.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)) { var xmlConfigValue = CloudConfigurationManager.GetSetting(property.Name); var liveConfigPropValue = (string)azureConfigType.GetProperty(property.Name).GetValue(config, null); if(string.IsNullOrEmpty(liveConfigPropValue)) { Trace.WriteLine(property.Name + " in live config is empty. Complementing with '" + xmlConfigValue + "' from ConfigurationManager."); property.SetValue(config, xmlConfigValue); } // do something with the property } return config; } private Hashtable GetConfigFromConfigurationManager() { Hashtable hashConfig = new Hashtable(); var configProperties = typeof(IAzureServiceConfiguration).GetProperties(); foreach(PropertyInfo prop in configProperties) { hashConfig.Add(prop.Name, CloudConfigurationManager.GetSetting(prop.Name)); } return hashConfig; } private XElement GetConfigXml() { XElement configXml = null; Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigXml"); if(!RoleEnvironment.IsAvailable/*as local web project*/ || RoleEnvironment.IsEmulated /*as azure emulator project*/) { Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigXml->!RoleEnvironment.IsAvailable || RoleEnvironment.IsEmulated"); try { var localConfigFile = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.EnumerateFiles( "*Local.cscfg", SearchOption.AllDirectories).FirstOrDefault(); XmlDocument doc = new XmlDocument(); doc.Load(localConfigFile.FullName); configXml = XElement.Parse(doc.InnerXml); } catch(Exception exception) // happens in some projects when using Full Emulator { Trace.WriteLine(exception.Message); Trace.WriteLine(exception.StackTrace); throw; // intended - just marking - will catch it above } } else { Trace.WriteLine("DefaultAzureServiceConfigurationProvider->GetConfigXml->RoleEnvironment ->in cloud"); var managementCertificate = new X509Certificate2(Convert.FromBase64String(_managementCertContents)); var credentials = new CertificateCloudCredentials(_subscriptionId, managementCertificate); var computeManagementClient = new ComputeManagementClient(credentials); var response = computeManagementClient.HostedServices.GetDetailed(_cloudServiceName); var deployment = response.Deployments.FirstOrDefault(d => d.DeploymentSlot == DeploymentSlot.Production); if(deployment != null) { var config = deployment.Configuration; configXml = XElement.Parse(config); } } return configXml; } } internal static class TypeHelpers { public static bool IsNumber(this object value) { return value is sbyte || value is byte || value is short || value is ushort || value is int || value is uint || value is long || value is ulong || value is float || value is double || value is decimal; } public static bool IsString(this object value) { return value is string; } } } 
+1
Jun 29 '15 at 14:45
source share



All Articles