Which values does WebHost read from appsettings.json - asp.net-core

In .Net Core you can self host a web server using WebHost. There is a method called CreateDefaultBuilder(), to which the Microsoft documentation states the following:
CreateDefaultBuilder performs the following tasks:
Loads app configuration from:
appsettings.json.
However, there doesn't seem to be any documentation on which parameters you can put into appsettings.json to have the WebHost automatically get configuration values other than the default values.
For example, I tried adding the following to my appsettings.json, but the server is started with http://localhost:5000 regardless:
{
"Kestrel" : {
"urls" : "http://*:8080"
},
"server" : {
"urls" : "http://*:8080"
}
}
I know I can read appsettings.json myself using ConfigurationBuilder, but that sort of defeats the purpose of the documentation
So, what do I need to put into my appsettings.json file to have CreateDefaultBuilder() not use the default values? A list of all possible values to put into appsettings.json would be welcome as well.

Why does CreateDefaultBuilder not configure the host with appsettings.json values?
Part of the answer is to distinguish between host and app configuration. The documentation says that CreateDefaultBuilder...
Loads host configuration from:
Environment variables prefixed with ASPNETCORE_ ...
Command-line arguments.
Loads app configuration from:
appsettings.json.
appsettings.{Environment}.json.
From within CreateDefaultBuilder, the reason that appsettings.json does not automatically affect the host, is that those settings are configuring the app, and the app config does not affect the host config. The documentation indicates that when it says:
IWebHostBuilder configuration is added to the app's configuration, but the converse isn't true — ConfigureAppConfiguration doesn't affect the IWebHostBuilder configuration.
Looking at the source code shows that the CreateDefaultBuilder method only adds the appsettings.json values from within its call to ConfigureAppConfiguration. That is why those values are not automatically impacting the host.
How can we configure the host with values from a *.json file?
CreateDefaultBuilder does not automatically configure the host with a *.json file. We need to do that manually, and the documentation specifies how. In the example the file is named hostsettings.json, and the example adds it explicitly like this:
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.json")
.Build();
return WebHost.CreateDefaultBuilder(args)
// this impacts *both* host and app config
.UseConfiguration(config)
.UseStartup<Startup>();
There is no magic in the name hostsettings.json. In fact, we could combine our host settings and our app settings into one file named appsettings.json. The way CreateDefaultBuilder works encourages us to keep those settings somewhat separate.
What keys can we put in a *.json file to configure the host?
This is the list of keys that we can use to configure the host:
"applicationName"
"startupAssembly"
"hostingStartupAssemblies"
"hostingStartupExcludeAssemblies"
"detailedErrors"
"environment"
"webroot"
"captureStartupErrors"
"urls"
"contentRoot"
"preferHostingUrls"
"preventHostingStartup"
"suppressStatusMessages"
"shutdownTimeoutSeconds"

Related

How to set up the remote host and Bearer configuration within Angular Template for .Net 6?

I can't find a way to figure out where is the host name configuration provided for the SPA application to connect to.
The command passed into the application from ASP.NET Core server while running the SPA is
ng serve --port 44472 --ssl --ssl-cert %APPDATA%\ASP.NET\https\%npm_package_name%.pem --ssl-key %APPDATA%\ASP.NET\https\%npm_package_name%.key
And I could not find any of the above strings localhost:7219, or 5219, or 7219 in the ClientApp / ClientApp/src folder (7219 and 5219 are the server ports and 44472 is the client npm port).
Do the server URLs passed from launchSettings.json asp project directly?
If so, if there a way to configure the server URLs directly from ClientApp if the client application is run from a different host, other than localhost (any where the settings (are | should be) stored)?
I can see the #Injected service everywhere but where does it store the settings is unclear (for how to configure this injected BASE_URL?):
constructor(http: HttpClient, #Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'weatherforecast').subscribe((result : any) => {
this.forecasts = result;
}, (error : any) => console.error(error));
}
The derived question is: should by default the client Bearer authorization also work for a remote host?
The remote host for example is github pages. How to properly set the remote host configuration within client application for a particular webpack deployment with angular-cli-ghpages if the CORS hosts are configured within Program.cs? Should the client configuration for a remote host (apart from localhost) or server CORS configuration, include additional "Bearer-Cors" configuration (as for the certificate npm start script mentioned in the question above – should it be just skipped without any parameters passed in it)?
Are there any comprehensive guidelines on this subject?
Half of the answer to this question is that the template uses proxy config, which is described here https://angular.io/guide/build#proxying-to-a-backend-server and stores the configuration in proxy.conf.js within ClientApp folder. I will try to extend my answer with any found information in the future.
Update: The second part of the answer is to add the Cookie.SameSite = SameSiteMode.None; cookie authorization configuration in Startup.cs / Program.cs. Take a look at the solution: https://stackoverflow.com/a/75239406/6897369

How can appSettings.{environment}.json be loaded before environment is known? (AspNetCore)

According to microsoft blog the ASPNETCORE_ENVIRONMENT variable is loaded in order:
appsettings.json file
appsettings.{env.EnvironmentName}.json file
The local User Secrets File
Environment Variables
Command Line Arguments (or equivalently launchSettings.json)
and "The last key loaded wins".
Questions:
But how can the file appsettings.{env.EnvironmentName}.json be loaded before the final Environment is known?
Can it happen that I set 'Staging' environment through command-line and appSettings.Development.json is loaded because during step 2 it is not yet known?
There are two sets of configuration for an ASP.NET Core application:
The configuration for the WebHost.
The configuration for the application itself.
First the WebHost configuration is built (source):
_config = new ConfigurationBuilder()
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.Build();
As the source code shows, the configuration for the WebHost uses only environment variables and only those that are prefixed with ASPNETCORE_. One of those environment variables is, unsurprisingly, ASPNETCORE_ENVIRONMENT.
A little later down the line, an implementation of IHostingEnvironment is instantiated. This ends up using _config to retrieve a configuration setting named environment, which comes from the ASPNETCORE_ENVIRONMENT variable. If there is no such value, it defaults to Production.
Next up, the configuration for the application itself gets built. At step 2 in your question, the value of env.EnvironmentName is from the IHostingEnvironment I've already mentioned. If you were to set an environment value of e.g. Staging as a command-line argument, it would not change the value used in the WebHost configuration, as this applies only to the application configuration.
Andew Lock goes into more detail about how this all works and also demonstrates how to configure the WebHost to use additional configuration sources.

How to isolate connectionStrings in separated file in asp.net core?

I am new to asp.net core and I am wondering how to put connectionStrings in separated file(json file) and ignore it so every developer can modify it to add his local connectionStrings?
In Asp.net I used to put connectionStrings in separated file (ex connectionStrings.config) and ignore it on git. Then inside web.config adding the following configuration:
<connectionStrings configSource="connectionStrings.config" />
So could you please guide me to how I can achieve that using asp.net core?
use a ConfigureAppConfiguration in your Program class
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration(builder =>
{
builder.AddJsonFile("appsetting.json");
builder.AddXmlFile("connectionStrings.config"));
});
With .NET Core or ASP.NET Core we don't use web.configs or app.configs for that purpose anymore. There is a new configuration-system built by Microsoft. By default, the webhost builds a configuration that includes these in that order
appsettings.json, optional
appsettings.{environment}.json, optional
environment-variables
In your case you will want to build one manually.
For that you need to have a reference to (included by default for visual studio templates via meta-package)
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.Configuration.EnvironmentVariables
Now instead of using the default configuration, build your own within your startup class.
public class Startup
{
// environment is being injected by the webhost
public Startup(IHostingEnvironment environment)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, "appsettings.json"), optional: false) // u can change that if you want to be optional
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, $"appsettings.{environment.environmentName}.json), optional: false)"
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, "connectionsettings.json"), optional: false)
.Build();
}
}
Then you can go ahead and access them kinda like before
configuration.GetConnectionString("MyConnectionString");
and your json file must look like that
"ConnectionStrings": {
"MyConnectionString": "some-connectionstring-value"
}
You could also use .NET user secrets, see:
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows
These have huge benefits:
the secret file is outside git folder, so it will never be committed by mistake.
you can edit the secret file from Visual Studio and it looks similar to appsettings.json
Basically you have the secrets configuration only active for development (that is the default), and for production you would have another configuration source (Key vault or environment variable, etc)

Problems with ASP.NET Core site using http.sys and Microsoft Edge

I'm having a ton of problems getting an ASP.NET Core 2.1 web application up and running. I need it to run under http.sys (WebListener) on a shared port (80 or 443). I'd also like it to automatically redirect from http (80) to https (443). Of course, I don't want to hard code the listener addresses for http.sys - I need to pull those from a configuration file, but they're hard coded for now. I reserved the appropriate URLs with netsh, but when I run the app I get a warning:
warn: Microsoft.AspNetCore.Server.HttpSys.MessagePump[0]
Overriding address(es) 'http://sharedhost.vbcoa.com:80/app/, https://sharedhost.vbcoa.com:443/app/'. Binding to endpoints added to UrlPrefixes instead.
The app starts, but I can't browse to it with Microsoft Edge at all. Any other web browser is fine - as long as I disable HTTPS. For some reason, the application is forwarding to port 5001, instead of 443.
I figured all of this out. There are four problems. I'll address them each individually.
When configuring http.sys, a warning is issued about overriding local URLs
The UseHttpSys extension method of IWebHostBuilder accepts an options argument with a UrlPrefixes property. However, this is not where you should configure URLs - even if you're using http.sys. You can hardcode them with the UseUrls extension method of IWebHostBuilder, but it would be better to pull it from configuration, which leads to the second problem:
Configuration should be read from appsettings.json
To specify which URLs you want to run the application on, add them to the "urls" element in appsettings.json, as follows:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"urls": "http://sharedhost.vbcoa.com:80/app/;https://sharedhost.vbcoa.com:443/app/"
}
Then you'll need to create a ConfigurationBuilder object, add the appsettings.json file to it, build the configuration (with the Build method) and tell IWebHostBuilder to use that configuration, with the UseConfiguration extension method:
public static void Main(string[] args)
{
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
var hostBuilder = WebHost.CreateDefaultBuilder(args)
.UseConfiguration(configBuilder.Build())
.UseHttpSys()
.UseStartup<Startup>();
hostBuilder.Build().Run();
}
Redirection goes to port 5001, not 443
HTTPS redirection is specified in the Configure method of Startup - that functionality comes out of the box. However, by default it will forward to port 5001, even if you have another port specified in your bound URLs from above. To override it, you need to inject HTTPS redirection options via a service. That's handled in the ConfigureServices method of Startup. Add the following line to that method:
services.AddHttpsRedirection(options => { options.HttpsPort = 443; });
Microsoft Edge won't show the web app, even though every other browser will
This is a problem with localhost loopback isolation in Windows Store apps. It seems to affect Windows 10 Enterprise, as discussed here: Microsoft Edge is not able to recognize localhost. To correct it, you need to do two things:
Make sure "Allow localhost loopback" is checked in Edge's "about:flags" page.
Launch a Command Prompt or Powershell Prompt as an Administrator and enter the following:
CheckNetIsolation LoopbackExempt -a -n=Microsoft.MicrosoftEdge_8wekyb3d8bbwe
That should do it!

Unable To Bind To Other Port with UseUrls

The following code just won't change the port to 9874. It stays the same in Project -> Debug -> Web Server Settings -> App URL -> "http://localhost:56021/", which uses the 56021 port. I am using VS 2017 to create .net core webapi project.
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://localhost:9874")
.Build();
It is the same even i change to Release mode.
Solve it by changing launchSettings.json.
If the setting is set in the above file, then what is the point to have UseUrls as it always refer to launchsettings.json setting?
In Project -> Debug -> Web Server Settings you see is a project profile that is used only when you try to run app from VS.
And in VS this is the responsibility of launchSettings.json to store and retrieve project configuration settings needed to run a project from VS only. In other words, launchSettings.json is ignored if you run app outside of VS (let's say from command line for example).
And back to .UseUrls method: it doesn't (and cannot, mainly because your app doesn't know about profiles at all) change above project profiles. Yes, this method indicates the IP addresses or host addresses with ports and protocols that the server should listen on for requests. But those settings will be applied to the Server instance that will be created on app start.