Azure Functions v2 - New .netcore Configuration and deployment - azure

Now that we can use the hugely flexible configuration engine from .NETCore - we can do something like this :
private static IConfigurationRoot SetConfig(ExecutionContext executionContext)
{
return new ConfigurationBuilder()
.SetBasePath(executionContext.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
}
Which is great as it allow you to put more complicated configuration data in the config file - for instance
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "<< removed >>",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"APPINSIGHTS_INSTRUMENTATIONKEY": "<< removed >>"
},
"MyCustomSettings": [
{
"ConnectionString": "<< removed >>",
"Folders": [
{
"ShareName": "share1",
"FolderName": "folder1"
},
{
"ShareName": "share2",
"FolderName": "folder2"
}
]
}
]
}
Again - great news! I can now get access to my strongly typed configuration with config["MyCustomSettings"]
What I don't get though - is how this can be deployed when publishing the function. Only the Values section is migrated to the Azure function Application Settings. I can obviously put this custom json in a json file and add it to the load statement like the local.settings.json
.AddJsonFile("my-custom-settings.json", optional: false, reloadOnChange: true)
but then this file has to be included in the deploy, and is not stored securely.
Any ideas?

This is not officially supported as of Nov 2019.
Warning
Avoid attempting to read values from files like local.settings.json or appsettings.{environment}.json on the Consumption plan. Values read from these files related to trigger connections aren't available as the app scales because the hosting infrastructure has no access to the configuration information.
There are so many blogs around advising to do this and it appears this may work if you only have a single instance, but as soon as the ScaleController triggers scaling, new instances will not be able to find the config files.
If you have triggers that use the %SettingName% syntax, they will not work as the function scales.
Functions team is considering possible Options (lol)
There is also the option of using the new App Configuration service but it is currently in preview and isn't available in all Azure regions.
It may be simpler to put your config in blob storage, and load it at startup? (Your blob store connectionstring will need to be in env variables)
So far the best we can do is to include your "not so secret" settings (things like MyThingTimeout or ExternalEndpointAddress) in a json file and use .AddJsonFile(...) and put secrets in KeyVault. This does force you to split your config and decide which goes where. (And also make sure your triggers only read from the Values section/Environment Variables)

Related

How to configure Serilog settings in Azure Function?

I’m in the process of creating my first production Azure Function and I’m trying to write log information to a local file and then eventually to Blob Storage. The local file is more for development troubleshooting and then ultimately I would like to have production information stored in Blob Storage. I’m not only new with Azure Functions but I’m also new with Serilog. I’ve used NLog in all my other applications but couldn’t get it to work with Azure Functions.
Currently I’m trying to get the local log working. I actually seem to have it working but I’m not understanding how I can tweak a couple things.
The first thing I’m trying to change is the amount of information that is getting logged. It seems to be logging a whole bunch of system type of information like Request info to the blob storage. There is so much stuff getting logged that what entry I'm adding in code gets lost. It looks like all the system entries are marked as Information which is why it’s probably showing up in my log. However, I would like to see if I could get it to only log data from when I specifically call the logger.Information(“some text”) in my code. Is there a way to suppress all of the Microsoft system information?
Second thing is how I can I make the Serilog configuration come from my local.settings.json file. Below is a sample of my file and I’m not sure if I would add the configuration information in the Values: property or if I would put it outside of that property into its own property? I’m assuming it would be in it’s own property but so far all my custom settings have been coming from the Values: property?
Do I need to add the Serilog.Settings.Configuration NuGet package? If so, then I’m not understanding how I configure my Startup.cs file to get the information from the local settings file instead of configuring the settings directly in code. Eventually, I would like to add it to Dependency Injection so I can use the logger in other classes as well.
Startup.cs
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient<IDataManager, DataManager>();
ConfigureServices(builder.Services).BuildServiceProvider(true);
}
private IServiceCollection ConfigureServices(IServiceCollection services)
{
services
.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(
new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File(#"D:\logs\AzureFunction\log_.txt", rollingInterval: RollingInterval.Day)
.CreateLogger())
);
return services;
}
Local.settings.json
{
"IsEncrypted": false,
"Values": {
"ProcessLookBackDays": "90",
"SqlConnection": "connection info",
"StorageConnection": "connection info"
"AzureWebJobsStorage": "connection info"
"InputContainer": "test-files",
"InputFolder": "input",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
},
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information"
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "D:\\logs\\AzureFunction\\log_.log",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {CorrelationId} {Level:u3}] {Username} {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
Setting up configuration in local-setting. Json will not reflect in the azure function app. local-setting as the name suggest is for local use only while with azure you need to use the app setting and read them.
Just add a new setting in the app setting and you can then use the below code to read the settings.
var appsettings = Environment.GetEnvironmentVariable("Name of the setting");
When you want to use the external configuration with serilog then you can use the Serilog.Settings.Configuration.
Now you can configure the minimum level of a log event so all the log event with less importance than the specified minimum level will not be logged.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information)
.CreateLogger();
Here we specify two things the .MinimumLevel.Debug() and restrictedToMinimumLevel this attribute dictates the minimum level for the that particular sink. A sink is just a place where you can log, they are configured using the Writeto tag. for e.g., in the above code the sink is a console. There are other sink too.
The minimum levels are verbose Debug, information, warning, error, fatal.
Reference:-
Read configuration from app setting by Ashish Patel
Use serilog to filter the logs
Serilog setting configuration

Access Azure App Service ConnectionString from ASP.NET Core

I've got an azure app service that I've set up like this:
But when I call IConfiguration.GetConnectionString("db") I get null back.
I've read articles like this https://mderriey.com/2018/08/21/azure-app-service-connection-strings-and-asp-net-core/ which say "it just works", but they're all several years old. I assume something's changed, but what?
Enumerating over all settings in my IConfiguration object I've got no connection strings. I do in development, where my appsettings.development.json has a connectionStrings: { db: "" } defined.
I can see and read the ENV variable: POSTGRESQLCONNSTR_db from within code, and it's value is correct (what I've set via the Azure portal).
Should I expect to be able to do IConfiguration.GetConnectionString("db")? Or am I expected to switch between reading env variables in prod vs dev.
Do I need to include some nuget package to make IConfiguration work under Azure with these ENV variables and their mad prefixes?
My startup.cs basically looks like:
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
public IConfiguration Configuration { get; }
Nothing else in there of interest to this question.
The POSTGRESQLCONNSTR_ prefix isn't supported by the environment variables configuration provider. The docs shows this, in an indirect fashion, where it states that the following prefixes are supported:
CUSTOMCONNSTR_
MYSQLCONNSTR_
SQLAZURECONNSTR_
SQLCONNSTR_
It's also apparent in the source code for the provider.
There are a couple of options for working around this:
Change the Type to Custom in the Connection strings section of the Azure portal.
Change to an Application setting of ConectionStrings:db in the Azure portal.
This is being tracked on GitHub: https://github.com/dotnet/runtime/issues/36123.
I got confused as well, so here it is:
You have two options to specify Connection String locally:
launchSettings.json (environmentVariables section)
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"SQLAZURECONNSTR_SomeConnectionString": "DefaultEndpointsProtocol=blah"
}
appSettings.json
"ConnectionStrings": {
"SomeConnectionString": "DefaultEndpointsProtocol=blah"
}
Having either way will allow you to get the connection string setting by calling:
IConfiguration.GetConnectionString("SomeConnectionString")
Function call above will also work when deployed to Azure, as it is using EnvironmentVariables configuration provider to read settings.
Instead of getting the config from the interface
IConfiguration.GetConnectionString("db")
try to get it from
Configuration.GetConnectionString("db")
And in production you have an empty string in production.appsetting.json and add the value in azure(appservice) configuration directly under connectionstrings(this will override the json setting file). And no nugets are needed for reading from appsettings

Using ConfigurationBuilder in FunctionsStartup

I have an Azure function, and I'm using the DI system in order to register some types; for example:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services
.AddTransient<IMyInterface, MyClass>()
. . . etc
However, I also was to register some data from my environment settings. Inside the function itself, I can get the ExecutionContext, and so I can do this:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
However, in the FunctionsStartup, I don't have access to the ExecutionContext. Is there a way that I can either get the ExecutionContext from the FunctionsStartup class or, alternatively, another way to determine the current running directory, so that I can set the base path?
While the checked answer to this question is correct, I thought it lacked some depth as to why. The first thing you should know is that under the covers an Azure Function uses the same ConfigurationBuilder as found in an ASP.NET Core application but with a different set of providers. Unlike ASP.NET Core which is extremely well documented (https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) this is not the case for Azure Functions.
To understand this set of providers you can place the following line of code in the Configure(IFunctionsHostBuilder builder) method of your FunctionStartup class,
var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
place a debug break point after the command, execute your function in debug mode and do a Quick Watch… on the configuration variable (right click the variable name to select Quick Watch…).
The result of this dive into the code execution is the following list of providers.
Microsoft.Extensions.Configuration.ChainedConfigurationProvider
MemoryConfigurationProvider
HostJsonFileConfigurationProvider
JsonConfigurationProvider for 'appsettings.json' (Optional)
EnvironmentVariablesConfigurationProvider
MemoryConfigurationProvider
The ChainedConfigurationProvider adds an existing IConfiguration as a source. In the default configuration case, adds the host configuration and setting it as the first source for the app configuration.
The first MemoryConfigurationProvider adds the key/value {[AzureWebJobsConfigurationSection, AzureFunctionsJobHost]}. At least it does this in the Development environment. At the time I am writing this I can find no documentation on the purpose of this MemoryConfigurationProvider or AzureWebJobsConfigurationSection.
The HostJsonFileConfigurationProvider is another one of those under the covers undocumented providers, however in looking at documentation on host.json (https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json) it appears to be responsible for pulling this metadata.
The JsonConfigurationProvider for appsettings.json appears to be an obvious correlation to ASP.NET Core’s use of appsettings.json except for one thing which is it does not work. After some investigation I found that the Source FileProvider Root was not set to the applications root folder where the file is located but instead some obscure AppData folder (C:\Users%USERNANE%\AppData\Local\AzureFunctionsTools\Releases\3.15.0\cli_x64). Go fish.
The EnvironmentVariablesConfigurationProvider loads the environment variable key-value pairs.
The second MemoryConfigurationProvider adds the key/value {[AzureFunctionsJobHost:logging:console:isEnabled, false]}. At least it does this in the Development environment. Again, at the time I am writing this I can find no documentation on the purpose of this MemoryConfigurationProvider or AzureFunctionsJobHost.
Now the interesting thing that needs to be pointed out is that no where in the configuration is any mention of local.settings.json. That’s because local.settings.json is NOT part of the ConfigurationBuilder process. Instead local.settings.json is part of Azure Functions Core Tools which lets you develop and test your functions on your local computer (https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local). The Azure Function Core Tools only focus on specific sections and key/values like IsEncrypted, the Values and ConnectionString sections, etc. as defined in the documentation (https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file). What happens to these key/values is also unique. For example, key/values in the Values section are inserted into the environment as variables. Most developers don’t even notice that local.settings.json is by default set to be ignored by Git which also makes it problematic should you remove the repository from you development environment only to restore it in the future. Something that ASP.NET Core has fixed with app secrets (https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets).
So, what happens if we create our own configuration with ConfigurationBuilder as suggested in the original question
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
or using the example shown in one of the other answers?
ExecutionContextOptions executionContextOptions = builder.Services.BuildServiceProvider().GetService<IOptions<ExecutionContextOptions>>().Value;
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.SetBasePath(executionContextOptions.AppDirectory)
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", false)
.AddJsonFile("local.settings.json", true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
The following are just a few of the issues with both examples.
The second example is incorrectly ordered as AddEnvironmentVariables should come last.
Neither of the examples mentions the need for the following line of code.
List item
builder.Services.AddSingleton<IConfiguration>(configurationBuilder.Build());
Without this line the configuration only exist in the Configure(IFunctionsHostBuilder builder) method of your FunctionStartup class. However, with the line you replace the configuration your Azure Function build under the covers. This is not necessarily a good thing as you have no way of replacing providers like HostJsonFileConfigurationProvider.
Reading the local.settings.json file (.AddJsonFile("appsettings.json")) will NOT place the key/value pairs in the Values section into the configuration as individual key/value pairs as expected, but instead group them under the Values section. In other word, if for example you want to access {["AzureWebJobsStorage": ""]} in Values you might use the command configuration.GetValue("Values:AzureWebJobsStorage"). The problem is that Azure is expecting to access it by the key name "AzureWebJobsStorage". Even more interesting is the fact that since local.settings.json was never part of the ConfigurationBuilder process this is redundant as Azure Functions Core Tools has already placed these values into the environment. The only thing this will do is allow you to access sections and key/values not defined as part of local.settings.json (https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file). But why would you want to pull configuration values out of a file that will not be copied into your production code?
All of this brings us to a better way to affect changes to the configuration without destroying the default configuration build by Azure Function which is to override the ConfigureAppConfiguration method in your FunctionStartup class (https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources).
The following example takes the one provided in the documentation a step further by adding user secrets.
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
FunctionsHostBuilderContext context = builder.GetContext();
builder.ConfigurationBuilder
.SetBasePath(context.ApplicationRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{context.EnvironmentName}.json", optional: true, reloadOnChange: false)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true, true)
.AddEnvironmentVariables();
}
By default, configuration files such as appsettings.json are not automatically copied to the Azure Function output folder. Be sure to review the documentation (https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources) for modifications to your .csproj file. Also note that due to the way the method appends the existing providers it is necessary to always end with .AddEnvironmentVariables().
You don't need any Configuration object in Azure Functions (v2). All the app settings get injected as Environment variables. So you can do just a simple Environment.GetEnvironmentVariable()
When running locally the local.settings.json gets read in the same way.
see here: https://learn.microsoft.com/en-us/sandbox/functions-recipes/environment-variables?tabs=csharp
There's a solid way to do this, answered here:
Get root directory of Azure Function App v2
The fact that Function Apps use environment variables as the typical way to get configuration is, while true, not optimal IMO. The ability to acquire an appsettings.json file in addition to items that deserve to be environment variables has its place.
The number of env vars being set via the DevOps task: "Azure App Service Deploy" option "Application and Configuration Settings" > "App settings" gets completely out of hand.
This is my implementation of it at the time of this writing:
ExecutionContextOptions executionContextOptions = builder.Services.BuildServiceProvider().GetService<IOptions<ExecutionContextOptions>>().Value;
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.SetBasePath(executionContextOptions.AppDirectory)
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", false)
.AddJsonFile("local.settings.json", true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
This allows me to leverage my release process variables to do environment specific "JSON variable substitution" for the bulk of my configuration, which lives in a nicely structured appsettings.json that is set to Copy Always. Notice that the loading of appsettings.json is set to not optional (the false setting), while I have local settings and secrets set to optional to accommodate local development.
appsettings.json can then be formatted nice and structured like this. Release variables named properly, e.g. "MyConfig.Setting" will replace the value properly if you set your release to do JSON variable substitution.
{
"Environment": "dev",
"APPINSIGHTS_INSTRUMENTATIONKEY": "<guid>",
"MyConfig": {
"Setting": "foo-bar-baz"
}
}
While local.settings.json remains in the flat style:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=<accountname>;AccountKey=<accountkey>;EndpointSuffix=core.windows.net",
"Strickland:Propane:Config": "Dammit, Bobby!"
}
}
In addition, I set some App settings (env vars) to Azure KeyVault References in the release process, as well as the minimum settings that are required for Azure Function runtime to start properly and communicate properly with app insights live metrics.
Hope this helps someone who, like me, hates the ever-growing mass of -Variable.Name "$(ReleaseVariableName)" items in App settings. :)
Unfortunately, at present there is no standard way to get the local running directory. It would be best if ExecutionContext or something similar exposed this.
In the absence of a standard way, I am using AzureWebJobsScriptRoot environment variable to get the current working directory, but it only works locally. In azure environment, I am using Environment.GetEnvironmentVariable("HOME")}\\site\\wwwroot.
I posted a code for this in response to a similar question here:
Azure Functions, how to have multiple .json config files
There is also a similar solution at this github issue.
You might want to use GetContext().ApplicationRootPath, for example:
[assembly:FunctionsStartup(typeof(SampleFunction.FunctionsAppStartup))]
namespace SampleFunction
{
public class FunctionsAppStartup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
string appRootPath = builder.GetContext().ApplicationRootPath;
// ...
}
}
}

Implementing Application Insight to Azure Function App

Anyone know of any god guide for this?
First i created an Application Insight Resource and put:
APPINSIGHTS_INSTRUMENTATIONKEY = "INSTRUMENTATION KEY"
in the Function Apps Application Settings.
I have tried implementering the nuget package for the funtion app like this.
Createing a project.json file and pasting this:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ApplicationInsights": "2.1.0"
}
}
}
}
It installed the nuget package (i could see it in the log, everything went well).
After that i put these snippets in my code to use the telemetry.TrackException(exception) functionality:
First...
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
Then:
var telemetry = new TelemetryClient(new TelemetryConfiguration("INSTRUMENTATION KEY"));
and in my catch:
telemetry.TrackException(e);
and when i try to save my Function app i get this error:
error CS1729: 'TelemetryConfiguration' does not contain a constructor that takes 1 arguments
You don't need to use reference the Application Insights library to use it with Functions. If you've already set the APPINSIGHTS_INSTRUMENTATIONKEY application setting, you can simply add the ILogger interface as a parameter to your function and it will automatically send the log data to your Application Insights instance.
Full documentation can be found here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-monitoring
Addition to #ChrisGillum answer for .Net Core 3.1 Azure Function:
If you create a new Azure Function with Http trigger from Visual Studio the following line will exist in the example:
log.LogInformation("C# HTTP trigger function processed a request.");
Add "APPINSIGHTS_INSTRUMENTATIONKEY" to local.settings.json Values.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"APPINSIGHTS_INSTRUMENTATIONKEY": "<YOUR_GUID>"
},
}
Note that the key must be in an app setting named APPINSIGHTS_INSTRUMENTATIONKEY and nothing else.
Logging is then added automatically:
Complete guide for hosted values:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-monitoring?tabs=cmd#enable-application-insights-integration

Azure Web App error 500 on Connection String

I've a simple ASP.NET Core 1.0 application which seeds some data in to SQL Server in Azure. I've 2 databases, one is for development and other is for Production (Azure SQL), I'm using Identity. When I run my application on my local machine, it works fine, but when I deploy it I get the error 500 (Internal Server Error) with no further explanation here is my code.
if (CurrentEnvironment.IsDevelopment())
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
else if (CurrentEnvironment.IsStaging() || CurrentEnvironment.IsProduction())
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Environment.GetEnvironmentVariable("SQLCONNSTR_kConnectionString")));
}
If I change the environment setting from Production to Development using Azure Application Settings, it says that error is at Configuration.GetConnectionString("DefaultConnection") saying connection string cannot be null.
There is a special pattern to be used, when you want to set the Variables from Environmental Variables.
In Azure App Service you set up your connection string as "DefaultConnection" or "SQLCONNSTR_kConnectionString" respectively, but you need to use. So if your connection string is "DefaultConnection", your appsetting.json must look like this
"ConnectionStrings" : {
"DefaultConnection" : "..."
}
when you obtain it with Configuration.GetConnectionString("DefaultConnection") (alternatively you can get it via Configuration["ConnectionStrings:DefaultConnection"]).
If you load it from environmental variables, it's better to override the default connection string via
var builder = new ConfigurationBuilder()
.SetBasePath(hostEnv.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{hostEnv.EnvironmentName}.json", optional: true, reloadOnChange: true);
.AddEnvironmentVariables();
Then the environmental variables will automatically override your settings in the appsettings.json or appsettings.Production.json.
If you want to get it via Environment.GetEnvironmentVariable you need to make it Environment.GetEnvironmentVariable("ConnectionStrings__SQLCONNSTR_kConnectionString") on Linux and Environment.GetEnvironmentVariable("ConnectionStrings:SQLCONNSTR_kConnectionString") on Windows. It's on top of my head, but the convention was something similar to this
I might misunderstand what you meant by "Azure SQL", but if you're using hosted Azure DB, then the prefix for the environment variable will be SQLAZURECONNSTR_ instead of SQLCONNSTR_. The latter would be used, for example, if you have SQL on your own VM in Azure (IaaS).
Also, it may help you to break apart your combined line of:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Environment.GetEnvironmentVariable("SQLCONNSTR_kConnectionString")));
into separate lines, something like the following, then you might be able to diagnose the issue a bit easier.
var envConnectionString = Environment.GetEnvironmentVariable(...);
if (string.IsNullOrEmpty(envConnectionString))
{
// log error, throw exception, etc
}
else
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(envConnectionString)));
}
Thank for your respond, actually I resolved my issue. Since ASP.NET Core RC 2, we have to use
"publishOptions": {
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
] },
options in project.json in order work them. :)

Resources