Как правильно хранить строки подключения в переменных среды для извлечения по продуктам ASP.Net Core MVC-приложения

Я работаю над ASP.NET Core MVC-приложением, и у меня возникла проблема с моими строками подключения.

У меня есть переменная ASPNETCORE_ENVIRONMENT установленная для Production на моем ASPNETCORE_ENVIRONMENT сервере, а мой производственный сервер - это Windows Server 2012R2, работающий с IIS. У меня также есть DotNetCore.1.0.4_1.1.1-WindowsHosting.exe, установленный на рабочем сервере.

Во время разработки я использую UserSecrets для хранения строки подключения. Это работает правильно.

Для производства я хочу, чтобы строки подключения в переменных среды на моем рабочем сервере, и это то, где у меня проблема. Я подозреваю, что это может быть так, как я структурирую переменную среды.

Когда я пытаюсь получить доступ к базе данных в процессе производства, я получаю сообщение об ошибке, указывающее в основном, что он не может разобрать строку соединения.

An exception occurred in the database while iterating the results of a query.

System.ArgumentException: Keyword not supported: '"server'.
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary'2 
parsetable, String connectionString, Boolean buildChain, Dictionary'2 synonyms)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary'2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)

Если я установил строку подключения в appSettings.json, производственный сервер будет работать нормально.

Итак, вот пример моего файла appSettings.json указанием строки подключения, которая работает в процессе производства;

{
  "ConnectionStrings": {
     "TestDb": "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"
  },

    ...
    ...
    ...
  }
}

Если я разворачиваю этот файл appSettings.json для производства, он работает нормально.

В моем приложении ASP.Net Core в файле Startup.cs у меня есть следующее:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    if (env.IsDevelopment())
    {
        // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
        builder.AddUserSecrets<Startup>();
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();

}

Я понимаю, что последний список builder.add... имеет приоритет, поэтому в моем случае, если в среде существует строка соединения, она должна иметь приоритет над чем-либо в настройках appsettings.

Поэтому в производстве, если я использую следующий файл appSettings.config;

{
  "ConnectionStrings": {
     "TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production. "
  },

    ...
    ...
    ...
  }
}

Не имеет значения, что у меня есть значение для ConnectionStrings:TestDb в этом файле appsettings.json если у меня есть переменная среды для строки подключения.

Ниже приведена переменная среды, которую я использую;

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

Однако, когда я использую эту настройку, я получаю сообщение об ошибке при попытке доступа к базе данных, указывающей на то, что она не может разобрать строку подключения.

Я должен предположить, что проблема заключается в том, как у меня есть строка соединения, указанная в переменной среды, но после долгого поиска в Интернете я не смог найти пример того, как должно выглядеть значение переменной среды. Например, мне нужно поставить ведущие и конечные одинарные кавычки вокруг всей строки? Нужны ли отдельные разделы строки соединения одинарные или двойные кавычки?

Любая помощь, такая как пример правильной строки соединения, определенной в переменной среды, будет с большой благодарностью.

Ответы

Ответ 1

В ваших переменных соединения есть опечатка/неправильное значение.

Что можно увидеть в этом выпуске, который вы вставили:

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

Вероятно, это произойдет при установке переменной через

$env:ConnectionStrings:MyDb = """Server=..."""

правильный способ - установить его без кавычек.

$env:ConnectionStrings:MyDb = "Server=..."

Старый ответ (для других пользователей, которые могут искать похожие проблемы)

Соглашением для строк подключения являются SQLCONNSTR_, MYSQLCONNSTR_, SQLAZURECONNSTR_ и CUSTOMCONNSTR_ которые используются Azure Web Apps, но также должны работать для самостоятельного хостинга, виртуальных машин или любого другого облачного провайдера.

Поэтому, если у вас есть переменная среды, называемая CUSTOMCONNSTR_TestDb она будет такой же, как и ее определение в appsettings.json в

{
    "connectionStrings": {
        "TestDb": "..."
    }
}

Он также переопределяет значение внутри него, если AddEnvironmentVariables() вызывается после .UseJsonFile(...). Последняя регистрация выигрывает.

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    // This one needs to be last
    .AddEnvironmentVariables();

Вы также можете использовать другие переменные для переопределения значений конфигурации. IIRC. ASPNETCORE_ является префиксом по умолчанию (но вы можете изменить его в AddEnvironmentVariables("MY_")).

Таким образом, ASPNETCORE_MySettings переопределяет Configuration["MySettings"] (или Configuration.Get("MySettings")) и ASPNETCORE_My__Settings (используйте двойной подчеркивание для иерархии уровней в Linux, читайте где : используется для получения конфигурации - Linux запрещает двоеточие в именах переменных) переопределяет Configuration["My:Settings"] так же, как

{
    "my": {
        "settings": "..."
    }
}

Если они не изменились в последнее время.

FWIW: Переменные среды/имена ключей конфигурации нечувствительны к регистру, насколько я помню.

Ответ 2

В вашей конфигурации у вас есть эта строка:

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

Это говорит вашей системе настройки, что в нем может быть JSON файл, который существует с настройками среды. Таким образом, вам нужен только файл, который существует в поле производства appSettings.Production.config содержащее что-то вроде этого:

{
  "ConnectionStrings": {
     "TestDb": "Server=...;Catalog=...;Etc=..."
  }
}

Значения здесь будут переопределять все, что указано в базовом файле настроек JSON.

Ответ 3

если вы не хотите хранить в appsettings, сохраните его в файле C:\Windows\System32\inetsrv\config\applicationHost.config. Он сможет работать.