Is there an alternate to Web.config Transormations in Asp.NET Core appsettings.json? - deployment

Is there an alternate to Web.config Transormations in Asp.NET Core appsettings.json?
I would like to change connection strings and other settins when deploying to staging.production server from VS.

First of all, keep in mind, that
ASP.NET Core’s configuration system has been re-architected from previous versions of ASP.NET, which relied on System.Configuration and XML configuration files like web.config. The new configuration model provides streamlined access to key/value based settings that can be retrieved from a variety of sources.
To work with settings in your ASP.NET application, it is recommended that you only instantiate a Configuration in your application’s Startup class. At its simplest, Configuration is just a collection of sources, which provide the ability to read and write name/value pairs.
ASP.NET Core provides built-in support for JSON, XML, and INI configuration files as sources and allows to choose source accordinly to current environment. The ASPNETCORE_ENVIRONMENT environment variable is used to setup/determine the current environment. Predefined values are Development, Staging, Production, but can be any custom also.
Lets say you want to use JSON file (named appsettings.json for convention) for storing connection string. What you need to do is to create a separate appsettings.{EnvironmentName}.json files (for each environment you have) like:
appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json
and load one of them accordingly to environment:
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
Read more about all of this in the “Configuration” chapter and the “Working with multiple environments” chapter of the ASP.NET Core documentation.

Yes, you must use environment variables on the target system.
ASP.NET Core references a particular environment variable, ASPNETCORE_ENVIRONMENT to describe the environment the application is currently running in. This variable can be set to any value you like, but three values are used by convention: Development, Staging, and Production. You will find these values used in the samples and templates provided with ASP.NET Core.
Determining the environment at runtime
The IHostingEnvironment service provides the core abstraction for working with environments. This service is provided by the ASP.NET hosting layer, and can be injected into your startup logic via Dependency Injection. The ASP.NET Core web site template in Visual Studio uses this approach to load environment-specific configuration files (if present) and to customize the app’s error handling settings. In both cases, this behavior is achieved by referring to the currently specified environment by calling EnvironmentName or IsEnvironment on the instance of IHostingEnvironment passed into the appropriate method.
https://docs.asp.net/en/latest/fundamentals/environments.html

Related

Embedding shared XML in Service Fabric Application Manifest

We are using Service Fabric framework with .net Core. One of the things which started to become a bit problematic is some of our services / applications need the same parameters - which we're retyping for each of the application manifests.
Is there a way of sharing an XML snippet where you can reference in the application manifest / so the Service Fabric Applications which are using the same parameters can just reference that shared snippet?
AFAIK, there is not way to provide the parameters on separate files, but you could update the default Deploy-FabricApplication.ps1 script to do so.
In you case you options are:
Create separate files and create a script to merge it before deployment.
Use a CI/CD process to do the configuration values and inject the values as shown here
Pass the shared values as JSON as a single parameter like shown here
Use a configuration server like Azure KeyVault and the applications load from there.
Is likely to doable in many other different ways, shouldn't be that difficult.

Adding an AuthorizationHandler via config

In WCF, you can add an authorization policy through the web.config by using the serviceAuthorization node in a service behavior. Is there a way to include an AuthorizationHandler in .NET Core WebAPI via config?
To be clear, I'm trying to replace this line in Startup.cs with something in the web.config:
services.AddSingleton<IAuthorizationHandler, MyAuthorizationHandler>();
web.config is only used for IIS specific config. Because of .net-core's cross platform nature they ditched coupling to web config for application configuration.
A web.config file is required when hosting the app in IIS or IIS Express. Settings in web.config enable the ASP.NET Core Module to launch the app and configure other IIS settings and modules.
Reference Configure an ASP.NET Core App: The web.config file
Startup is your entry point into the application where you can have some settings in the json file and have your code add/update the configuration based on that.
My thinking is that it would save having to recompile every time you want to add something because configuration options allows you to Reload configuration data with IOptionsSnapshot
Requires ASP.NET Core 1.1 or later.
IOptionsSnapshot supports reloading options with minimal processing overhead. In ASP.NET Core 1.1, IOptionsSnapshot is a snapshot of IOptionsMonitor<TOptions> and updates automatically whenever the monitor triggers changes based on the data source changing. In ASP.NET Core 2.0 and later, options are computed once per request when accessed and cached for the lifetime of the request.
Your authorization handler(s) would depend on the options and perform its function based on the configurations provided.

Building two different versions a given war with maven profiles and filtering from eclipse

I am trying to use maven profiles and filtering in order to produce two different versions of a given web archive (war):
A first one for local deployment to my local machine on localhost
A second one for remote deployment to cloudfoundry
There are a number of properties that differ according to whether the app is deployed to my local machine or to cloudfoundry.
Of course the difficult bit is that I am trying to do all this from STS/Eclipse and deploy from Eclipse to my local tomcat and to cloudfoundry...
Can anyone please provide advice, tips or suggestions?
If you are using Spring versioning 3.1+ the "profile" attribute for <beans> in the spring bean configuration xml would be the best choice. Take a look at the doc here: http://docs.cloudfoundry.com/frameworks/java/spring/spring.html#using-spring-profiles-to-conditionalize-cloud-foundry-configuration
Basically you need to specify at least 2 elements. One for your local properties (profile="default") and one for the properties when deployed to CF. The latter one should be defined as <beans profile="cloud">. When running locally the properties within "cloud" would be ignored and properties in "default" will take effect. When pushed to CF, CF will detect the profile named "cloud" and, which is better, inject corresponding datasource connection info of the services provisioned by CF itself. You can find the detailed CF-specified properties in that doc as well.
For more information about the profile attribute, see the doc here: http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
Consider having a single project per artifact generated. Hence one project generating your local deployment and one project generating your cloudfoundry deployment.
Overlays (http://maven.apache.org/plugins/maven-war-plugin/overlays.html) is the officially sanctioned way to bake in extra files in an existing WAR file, giving a new WAR artifact. Very useful but may be too slow for comfort while developing.

GlassFish 3.1.2 + Cluster + Web Container Properties

I have an issue in Glassfish regarding dealing with properties wehn setting up a web application We are moving from using Jetty to a clustered environment setup with GlassFish on Amazon AWS
Conventionally speaking when dealing with Servlets you are meant to use a .properties file when you want to parse in environment variables, however this causes issues when you use a distributed environment (you would have to place the .properties file in every cluster node). GlassFish has the ability to configure properties of the web container through their Admin Console, which means the properties would automatically distribute through the cluster
The problem is, I am getting random behavior regarding retrieving the variables. The first time I ran a test application, I couldn't retrieve the variables, however no it no longer works
Basically I am setting the environment variables through the admin UI. Under Configurations there are 3 configuration stetings, one for the cluster (usually named .config), one default-config and one server-config. Under Web Container, I have put a test property in all 3 of the called "someVal".
I then created a quick Scalatra app in Scala (which uses Servlet 2.5) and I used this line to attempt to get the properties
getServletContext.getInitParameter("someVal")
Any ideas what I am doing incorrectly, it always returns null?
Update
It appears what I was attempting to do isn't the "correct" way of doing things. So my question is, what is the standard way of providing specific application settings (outside of the .war and outside of runtime) when dealing with clusters in GlassFish. myfear stated that using a database is the standard approach, however I use these configuration settings themselves to define the JDBC connection
I got it. You are referring to the Web Container Settings
http://docs.oracle.com/cd/E18930_01/html/821-2431/abedw.html
I'm afraid that this never has been thought of as providing application specific configuration and I strongly believe that you will never be able to access those properties from the servlet context.
So, you could (should) use the servlet init params in web.xml if you are talking about application specific information. if you use
getServletContext().setInitParameter("param", "value");
you might be able to set them (at least for the runtime of the application). I'm not sure about cluster replication here. The normal way would be to have you configuration settings in the database.

Azure web.config per environment

I have a Azure project (Azure 1.3) in VS2010. There are 2 webroles, one web page project and one WCF project. In debug mode I want the web project to use a web.config for DEV enviroment, and when publishing the web.config for PROD must be used.
What is the best way to do this ?
Currently I am facing issues when using a Web.Debug.config with transform XSLT. It doesn't seem to work in Azure....
Solve your problem a different way. Think about the web.config always being static and never changing when working with Azure. What does change is your ServiceConfiguration.cscfg.
What we have done is created our own configuration provider that first checks the ServiceConfiguration.cscfg and then falls back to the web.config if the setting/connection string is't there. This allows us to run servers in IIS/WCF directly during development and then to have different settings when deployed to Azure. There are some circumstances where you have to use web.config (yes, I'm referring to WCF here) and in those cases you have to write code and create convention instead of storing everything in web.config. I have a blog post where I show an example of how I did this when dealing with WIF (Windows Identity Foundation) and Azure.
I agree with Mose, excellent question!
Visual Studio 2010 includes a solution for this type of problem, web.config transforms. If you look at your web role you'll notice it includes Web.Debug.config and Web.Release.config along with the traditional web.config. These files are used to transform the web.config during deployment.
The canonical example is "I need different database connection strings for development and release" but it also fits your situation.
There is an excellent blog post from the Visual Web Developer Team that explains how to use this feature (don't bother with the MSDN docs, I know how it works and still don't understand the docs). Check out http://blogs.msdn.com/b/webdevtools/archive/2009/05/04/web-deployment-web-config-transformation.aspx
I like this question !
For worker roles, I solved this problem by detecting the environment at runtime and launching my 'application' in a new AppDomain with a custom configuration :
bot.cloud.config
bot.dev.config
bot.win.config
This is incredibly efficient !
I'd like to do the same with web projects, because using the Azure specific configuration is a lot of trouble :
Both config are not in the same place, which is time-consuming when debugging
You have to learn a new way of writing something that sould be standard
Sometime you'll wonder if the app falled back on web.config because of a stupid syntax error
I'm still searching the right way to do that, like in this post
Another possible solution is to have two CloudService projects, each one with specific ServiceConfiguration.cscfg(dev/prod). Develop using the Dev, but deploy the Prod.
Currently I am facing issues when using a Web.Debug.config with
transform XSLT. It doesn't seem to work in Azure....
It depends on whether you want to make it work on your local machine or inside continuous integration.
For the local machine I tried to answer here: https://stackoverflow.com/a/9393533/182371
For the continuous integration it's even easier. When you build from the command line specifying the Configuration property value your configs WILL be transformed (no matter what it does when you build inside VS). So properly specifying build configurations for both cloud and web project will give you the correct output depending on build parameters.