Some background...
一些背景......
I've seen answers using ConfigurationManager, but I think what I'm trying to achieve is slightly different.
我已经看到了使用ConfigurationManager的答案,但我认为我想要实现的目标略有不同。
I am deploying MVC5 as Azure cloud service. The customer would like a single delivery package for Test/User Acceptance/Live with all (if possible) settings stored in Azure configuration settings. For our own appSettings values this isn't a problem, move them to the ServiceConfiguration.cscfg and read them with a call to CloudConfigurationManager.GetSetting
(which reads from Azure cscfg if deployed in an Azure role, or web.config if running locally in IIS during dev)
我正在将MVC5部署为Azure云服务。客户希望单个交付包用于测试/用户接受/实时,并在Azure配置设置中存储所有(如果可能)设置。对于我们自己的appSettings值,这不是问题,将它们移动到ServiceConfiguration.cscfg并通过调用CloudConfigurationManager.GetSetting(如果部署在Azure角色中从Azure cscfg读取,或者如果在本地运行则从web.config读取)来读取它们开发期间的IIS)
However, there was still a problem with Microsoft.Web.RedisSessionStateProvider - which only supports reading settings from web.config (I emailed the Devs and they confirmed this)
但是,Microsoft.Web.RedisSessionStateProvider仍然存在问题 - 它只支持从web.config读取设置(我通过电子邮件发送了Devs并确认了这一点)
I got around this by reading the connectionstring from the ServiceConfiguration.cscfg on Azure and stuffing it into the in-memory web.config as follows, which seemed a viable way of allowing MVC to do it's own configuration of the Session handling.
我通过从Azure上的ServiceConfiguration.cscfg读取连接字符串并将其填充到内存中的web.config中来解决这个问题,如下所示,这似乎是允许MVC自己配置会话处理的可行方法。
private void UpdateConfigurationSettings()
{
// Obtain the RuntimeConfig type.
var runtimeConfig = Type.GetType("System.Web.Configuration.RuntimeConfig, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
// Obtain the RuntimeConfig instance.
var runtimeConfigInstance = runtimeConfig.GetMethod("GetAppConfig", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
UpdateRedisSessionStateSettings(runtimeConfig, runtimeConfigInstance);
UpdateAppSettings(runtimeConfig, runtimeConfigInstance);
}
private static void UpdateRedisSessionStateSettings(Type runtimeConfig, object runtimeConfigInstance)
{
// Obtain the SessionStateSection instance.
SessionStateSection sessionStateSection =
(SessionStateSection)
runtimeConfig.GetProperty("SessionState", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(runtimeConfigInstance, null);
// Since the SessionStateSection is set to read only be dafault, we must make it writeable.
typeof (ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(sessionStateSection, false);
// Get the provider from the SessionStateSection
var provider = sessionStateSection.Providers[0];
// Since the provider is set to read only be dafault, we must make it writeable.
typeof (ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(provider, false);
// Update the connection string paramter of the provider
provider.Parameters.Set("connectionString", ConfigurationParameters.RedisCacheConnectionString);
// Just read it back - this is only for debugging so I can see that the value has been updated.
var c = provider.Parameters["connectionString"];
}
The problem is Active Directory
问题是Active Directory
My real problem now is the Azure Active Directory settings and I was hoping to do a similar thing, but I can't seem to access the appSettings section using the same method. Attempting to read the appSettings as follows gives a null pointer, and indeed if you debug into runtimeConfigInstance every other section is available - but not appSettings !
我现在真正的问题是Azure Active Directory设置,我希望做类似的事情,但我似乎无法使用相同的方法访问appSettings部分。尝试按如下方式读取appSettings会产生一个空指针,实际上如果调试到runtimeConfigInstance中,则每个其他部分都可用 - 但不是appSettings!
private void UpdateAppSettings(Type runtimeConfig, object runtimeConfigInstance)
{
// Obtain the AppSettings section instance.
AppSettingsSection appSettingsSection =
(AppSettingsSection)
runtimeConfig.GetProperty("appSettings", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(runtimeConfigInstance, null);
// Since the AppSettings section is set to read only be dafault, we must make it writeable.
typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(appSettingsSection, false);
}
So my question has 2 sides:
所以我的问题有两个方面:
-
Is it possible to access appSettings in the same manner without using ConfigurationManager and saving the file ?
是否可以在不使用ConfigurationManager并保存文件的情况下以相同方式访问appSettings?
-
Is there any other way of reading the Active Directory definition from Azure settings rather than in web.config to give us a single package deliverable where all settings are configurable on Azure ?
是否还有其他方法可以从Azure设置而不是web.config中读取Active Directory定义,以便为我们提供单个程序包可交付,其中所有设置都可在Azure上配置?
Note : I'm using the following to manipulate the FederationConfiguration
with values read from cscfg, but the appSettings keys ida:FederationMetadataLocation
ida:Realm
ida:AudienceUri
in the web.config need to be correct too..
注意:我正在使用以下操作来使用从cscfg读取的值来操作FederationConfiguration,但appSettings键ida:FederationMetadataLocation ida:Realm ida:web.config中的AudienceUri也需要正确。
private void FederatedAuthenticationOnFederationConfigurationCreated(object sender, FederationConfigurationCreatedEventArgs args)
{
args.FederationConfiguration.IdentityConfiguration.AudienceRestriction.AllowedAudienceUris[0] = new Uri(ConfigurationParameters.ActiveDirectoryAudienceUri);
args.FederationConfiguration.WsFederationConfiguration.Issuer = ConfigurationParameters.ActiveDirectoryIssuer;
args.FederationConfiguration.WsFederationConfiguration.Realm = ConfigurationParameters.ActiveDirectoryRealm;
}
1 个解决方案
#1
1
Here is the solution for you.
这是您的解决方案。
Step 1: Write your custom code on how to read your connection string. In this example I am first reading from the cloud configuration and falling back on web config.
第1步:编写有关如何读取连接字符串的自定义代码。在这个例子中,我首先从云配置中读取并回退到web配置。
using System;
using System.Configuration;
using Microsoft.Azure;
namespace Namespace1 {
public class RedisConnectionStringProvider {
public static string GetConnectionString() {
const string redisConnectionString="redisConnectionString";
var cloudConfigurationValue = CloudConfigurationManager.GetSetting(redisConnectionString);
if (!String.IsNullOrEmpty(cloudConfigurationValue))
return cloudConfigurationValue;
var connectionStringSettings = ConfigurationManager.ConnectionStrings[redisConnectionString];
if (connectionStringSettings == null) {
throw new ConfigurationErrorsException("A connection string is expected for " + redisConnectionString);
}
return connectionStringSettings.ConnectionString;
}
Step 2. Now, tell the provider to invoke your custom implementation for connection string.
步骤2.现在,告诉提供程序调用连接字符串的自定义实现。
<sessionState mode="Custom" timeout="60" customProvider="RedisSessionProvider">
<providers>
<add name="RedisSessionProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" settingsClassName="Namespace1.RedisConnectionStringProvider, AssemblyName, Culture=neutral" settingsMethodName="GetConnectionString"/>
</providers>
</sessionState>
#1
1
Here is the solution for you.
这是您的解决方案。
Step 1: Write your custom code on how to read your connection string. In this example I am first reading from the cloud configuration and falling back on web config.
第1步:编写有关如何读取连接字符串的自定义代码。在这个例子中,我首先从云配置中读取并回退到web配置。
using System;
using System.Configuration;
using Microsoft.Azure;
namespace Namespace1 {
public class RedisConnectionStringProvider {
public static string GetConnectionString() {
const string redisConnectionString="redisConnectionString";
var cloudConfigurationValue = CloudConfigurationManager.GetSetting(redisConnectionString);
if (!String.IsNullOrEmpty(cloudConfigurationValue))
return cloudConfigurationValue;
var connectionStringSettings = ConfigurationManager.ConnectionStrings[redisConnectionString];
if (connectionStringSettings == null) {
throw new ConfigurationErrorsException("A connection string is expected for " + redisConnectionString);
}
return connectionStringSettings.ConnectionString;
}
Step 2. Now, tell the provider to invoke your custom implementation for connection string.
步骤2.现在,告诉提供程序调用连接字符串的自定义实现。
<sessionState mode="Custom" timeout="60" customProvider="RedisSessionProvider">
<providers>
<add name="RedisSessionProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" settingsClassName="Namespace1.RedisConnectionStringProvider, AssemblyName, Culture=neutral" settingsMethodName="GetConnectionString"/>
</providers>
</sessionState>