在Azure上运行的Web应用程序没有启动并使用环境变量连接字符串(ASP,NET Core RC1)

时间:2016-05-03 18:38:08

标签: azure asp.net-core asp.net-core-mvc

Github link for reproduction.

我有一个ASP.NET Core(RC1)应用程序在本地工作正常。我遇到的问题是我的Azure应用程序没有接收到我的连接字符串。我已经向此提出了类似的问题,但我已经在this app.注意到了我的问题,它需要Azure上的一个应用程序来重现它。

这是我看到的问题。

首先,我的配置设置如下:

public Startup()
{ 
    var builder = new ConfigurationBuilder()
            .AddJsonFile("config.json")
            .AddEnvironmentVariables();
    mConfiguration = builder.Build();
}

EF7在这里设置:

public void ConfigureServices(IServiceCollection services)
{
    services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<FooDbContext>(options =>
            {
                // I'm assuming it's failing here. 
                // I'm not sure how to debug it running on Azure. 
                // All the developer exception page shows is:
                //  500 Internal Server Error "An error occurred while starting the application."
                options.UseSqlServer(mConfiguration["Data:ConnectionStringTest:ConnectionString"]);
            });
    services.AddScoped<IFooDataService, FooSqlDataService>();
}

我的config.json有:

{
  "Data": {
    "ConnectionStringTest": {
      "ConnectionString": "Data Source=(localdb)\\mssqllocaldb;Initial Catalog=ConnectionStringTest"
    }
  }
}

这应该被我在Azure中设置的连接字符串覆盖:

azure connection string snapshot

当访问Kudu SCM并查看Azure Web应用程序实例上的环境变量时,我看到以下内容:

SQLAZURECONNSTR_Data:ConnectionStringTest:ConnectionString = my_connection_string_here

我假设在运行时使用环境变量时,这是在引擎盖下使用的类:EnvironmentVariablesConfigurationProvider

2 个答案:

答案 0 :(得分:1)

好的,我找到了,这感觉很尴尬。

您似乎需要在Azure中的 EXCEPT 处使用Data:{my_connection_string_key}:ConnectionString。如果连接字符串以SQLAZURECONNSTR_为前缀,This environment variable converter将自动构造正确的连接字符串using this format

这意味着当您在Azure中设置连接字符串时,除了连接字符串的键之外,您需要省略 EVERYTHING 。请勿插入Data::ConnectionString ...而只需使用{connection_string_key}(请参阅上述格式)。如果您在Azure密钥/值对中包含整个格式,则EnvironmentVariablesConfigurationProvider会在其周围添加另一个Data::ConnectionString,从而产生类似Data:Data:{my_connection_string_key}:ConnectionString:ConnectionString的内容。

ConfigureServices(...)中,使用ASP期望的格式:

... options.UseSqlServer(mConfiguration["Data:ConnectionStringTest:ConnectionString"]);

因此,您可以在本地将此用于本地JSON,以便在开发/回退中进行测试:

{
  "Data": {
    "ConnectionStringTest": {
      "ConnectionString": "Data Source=(localdb)\\mssqllocaldb;Initial Catalog=ConnectionStringTest"
    }
  }
}

请确保您的Azure连接字符串具有该格式的中间部分(ConnectionStringTest使用此示例)。

enter image description here

这将使Azure中的环境变量看起来像原始格式:

SQLAZURECONNSTR_ConnectionStringTest = {insert connection string here}

EnvironmentVariablesConfigurationProvider将剥离Azure前缀字符串,并以硬编码格式包装您的密钥:Data:{0}:ConnectionString

答案 1 :(得分:1)

实验结果

为了增加您的出色答案,我做了一个本地实验,以确认SQLAZURECONNSTR_connection_string_key环境变量成为此配置:

mConfiguration["Data:connection_string_key:ConnectionString"]

本地实验

本地环境变量模拟名为connection_string_key的Azure SQL数据库连接字符串。

PS> $env:SQLAZURECONNSTR_connection_string_key = "an azure conn string"

以下代码将所有环境变量和配置部分转储到页面。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("# Environmental Variables \r\n");
        await DumpAllEnvVariables(context, Environment.GetEnvironmentVariables());

        await context.Response.WriteAsync("# Configuration Sections \r\n");
        await DumpAllConfigItems(context, mConfiguration.GetChildren());
    });
}

private async Task DumpAllEnvVariables(HttpContext context, IDictionary envVariables)
{
    foreach (var envVar in envVariables.Cast<DictionaryEntry>())
    {
        await context.Response.WriteAsync($"{envVar.Key}"); // : {envVar.Value}
        await context.Response.WriteAsync($"\r\n");
    }
}

private async Task DumpAllConfigItems(HttpContext context, 
    IEnumerable<IConfigurationSection> sections, string prefix = "")
{
    foreach (var section in sections)
    {
        await context.Response.WriteAsync($"{prefix}{section.Key}"); // : {envVar.Value}
        await context.Response.WriteAsync($"\r\n");

        if(section.GetChildren().Any())
        {
            await DumpAllConfigItems(context, section.GetChildren(), prefix + "  ");
        }
    }
}