如何在运行时从网络服务中获取CloudConfiguration的完整列表?(How to get

2019-10-23 12:03发布

ConfigurationManager中有AppSettings的名称 - 值集合,但CloudConfigurationManager只有GetSetting(string)方法,您可以通过1得到的配置设置1,如果你知道的关键。

有没有办法让角色运行的整个配置?

根本原因是,我想使强类型的配置,以抽象它拿走,让我的代码的可测试性。 使用CloudConfigurationManager直接是我想,我希望在测试中存根的抽象删除隐含的依赖。 所以我觉得这是现实。 这让我想起我的问题。

我不想使用图书馆像fx.configuration.azure因为我必须完全履行其依赖性,因为它需要一个基类继承。

Answer 1:

据我所知,有没有可用的直接的方法,这将给你这个信息。

但是有一个变通方法,您可以使用。 它涉及到利用服务管理API的的Get Deployment操作。 此操作将返回一个XML和元素之一,也是Configuration其中包含Base64编码格式的服务配置文件。 你可以阅读这个元素,将其转换成字符串并解析XML去ConfigurationSettings元素。 它的子元素包含了所有的设置。

对于这一点,你既可以写在服务管理REST API自己的包装或使用Azure Management Library

UPDATE

因此,这里的上市所有配置设置的代码示例Service Configuration File使用Azure Management Library 。 这是一个在很短的时间量一起砍死一个简单的控制台应用程序因而具有很大的改进:)的范围。 对于管理证书,我已经使用了数据从发布设置文件。

你只需要安装Azure Management Library在控制台应用程序NuGet包:

安装,包装Microsoft.WindowsAzure.Management.Libraries

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();
        }
    }
}


Answer 2:

下面是一个更新的实施,如果你在模拟器中运行与否,如果你在本地Web服务器或者没有正在运行的照顾。 返回它可以很容易地提取从Castle.DictionaryAdapter整个程序走字典后。 我共享代码在GitHub模板项目在这里 。 下面是摘录:

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;
        }

    }
}


文章来源: How to get full list of CloudConfiguration from inside a web service at runtime?