changing or updating app.config at runtime in wpf projects - wpf

How do we overwrite config file at runtime. I have four config files for DEV, TEST, UAT, PROD. Based on user selection I need to overwrite the default config file completely with one of the selection specific config files. These config files not only have appsettings section, but also has complex cutom sections and subelements with lot of attributes. I need to overwrite and refreshsections dynamically at runtime. I know there are so many articles on editing appsettings sections. But I want to completely overwrite the entire file. Your help in VB.net is appreciated.
I have custom sections :

Using ClickOnce, I do not believe you can or should change files within the installation folder because it is read-only... Therefore, you have a choice: go with an MSI install and a custom install action to switch in the appropriate config file or build up some custom configuration elements to encapsulate your different environments.
In our application, we have done the latter. We have something like the following custom configuration section in our main app.config.
<myApp defaultEnvironmentName="prod">
<environments>
<add name="prod" title="Production" description="Full production environment" injectionContainers="prod">
...
<!-- Add custom elements the affect your environment -->
...
</add>
<add name="qa" title="Quality Assurance" description="Full production environment except running off our mock database" injectionContainers="prod qa">
...
<!-- Add custom elements the affect your environment -->
...
</add>
</environments>
</myApp>
... <!-- Other elements that are common to all environments --> ...
Then we use a run-time flag or command line argument to enable you to switch between environments easily. The value of the environment in use is stored in a user Settings file so that on subsequent use the application will load the last used environment.
When we need to access something that varies per environment we directly call upon the custom configuration section's CurrentEnvironment property which utilised the above mentioned setting to work it out:
var title = MyAppSection.Configured.CurrentEnvironment.Title;
Note that here, MyAppSection.Configured is just a singleton instance that loads based on ConfigurationManager.GetSection(...).
I realise the prospect of a boat-load of configuration code is the last thing you want but it will let you clearly define and isolate your environment variables within the config files.

Related

Different branding for same codebase

Im in a project where we will create different sites using the same codebase.
I would like to have a brand style and config for each site which I specify somehow in my build process.
Anyone have an idea of the best way to achieve this ?
I would treat the different sites in much the same way I'd treat different environment (dev, test, prod). If there aren't a lot of changes, just use environment variables on each server where the site will run that define which site it is. Your code can then conditionally do things (e.g. add a class site-x to the body for styling).
You can use something like dotenv to make setting environment vars easier (remember Windows does it differently to *NIX) if you're setting environments in a script. That way you're changing a file rather then actual environment variables when you want to test what a particular site looks like.
If there are many different config items that are different between sites then you can have multiple config files (config-site-one.js, config-site-two.js) and a central config.js file that returns the correct config based on some environment variable like MY_SITE_NAME.
However if you actually want to package up the site to 'send' somewhere (?) then you could run your build command with a flag like webpack blahblahblah --site=site-one.
You can use yargs to get that 'site' variable and use it in your build process however you like.

Cross-contamination between AngularJS tests

We have a configuration file that we use in our AngularJS app. Because we need our configuration information during the build phase, we define it as a value. The configuration file contains information about where to find the assets for one of several Assessments, so we have a configurationService with an updateAssessment() function that looks in the configuration file at the various Assessments that are defined and then copies the properties from the specific Assessment into another value, assessmentSettings.
We have some situations where we want to read in some additional settings from an XML files, but when those settings are already provided as part of the configuration for that Assessment, we want to ignore them. I have a test that checks that this is done and it runs and passes.
However, massaging the project configuration value, then calling configurationService.updateAssessment(1) in that test causes 41 other tests in different files to fail. My understanding is that Angular should be torn down and brought back up for each test and should certainly not cross-contaminate across different files. Is there something different about values that would cause this to happen?
Note that the project itself seems to load and run fine. I haven't provided code examples because it would be a fair amount of code and I don't think it would be that enlightening. Angular 1.3.

Angular Constant Best Practice

I have an angular constant which defines webservice end point
angular.module('myModule').constant('mywebservice_url', 'http://192.168.1.100')
The problem is that for dev I have a different end point while staging and production its different. Every time I try to check in to git I have to manually reset this file.
Is there any way git permenantly ignore this file but checks out the file while clone or checkout?
Is there any way I can make angular pickup file dynamically from something like environment variable.
NOTE: I don't want to depend on server to do this, ie I don't want to use apach SSI or any of those technologies as it will work only one set of servers.
Delaying the injection via backend processing. I usually just create a global object on html page called pageSettings which values like this is getting injected from the backend, i.e. environment variables, etc. and just pass that global pageSettings object into that angular constant or value.
Build system injection. If you don't have a backend, i.e. pure SPA... maybe you can put this inside your build system, i.e. create multiple task for building the different environments in gulp or grunt and replace that value during the build process.
In e.a. your app init code:
var x = location.hostname;
Then define 2 different constants.
One based off the domain name of your develop environment and one for your production.

How to set up different databases per environment in Play 2.0?

I'd like my Play app to use different databases for test, local and production (production is Heroku) environments.
In application.conf I have:
db.default.driver=org.postgresql.Driver
%dev.db.default.url="jdbc:postgresql://localhost/foobar"
%test.db.default.url="jdbc:postgresql://localhost/foobar-test"
%prod.db.default.url=${DATABASE_URL}
This doesn't seem to work. When I run play test or play run,
all DB access fails with:
Configuration error [Missing configuration [db.default.url]] (Configuration.scala:258)
I have a few questions about this:
In general, I'm a little confused about how databases are configured
in Play: it looks like there's plain db, db.[DBNAME] and db.
[DBNAME].url and different tutorials make different choices among
those. Certain expressions that seem like they should work (e.g. db.default.url = "jdbc:..." fail with an error that a string was provided where an object was expected).
I've seen other people suggest that I create separate prod.conf, dev.conf and test.conf files that each include application.conf and then contain DB-specific configuration. But in that case, how do I specify what database to use when I run test from the Play console?
Is the %env syntax supposed to work in Play 2?
What's the correct way to specify an environment for play test to use?
In Play 2 there aren't different config environments. Instead you just set or override the config parameters in the conf/application.conf file. One way to do it is on the play command line, like:
play -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url=$DATABASE_URL ~run
You can also tell Play to use a different config file:
play -Dconfig.file=conf/prod.conf ~run
For an example Procfile for Heroku, see:
https://github.com/jamesward/play2bars/blob/scala-anorm/Procfile
More details in the Play Docs:
http://www.playframework.org/documentation/2.0/Configuration
At least in Play 2.1.1 it is possibly to override configuration values with environment variables, if they are set. (For details see: http://www.playframework.com/documentation/2.1.1/ProductionConfiguration)
So you can set the following in your conf/application.conf:
db.default.url="jdbc:mysql://localhost:3306/my-db-name"
db.default.url=${?DATABASE_URL_DB}
per default it will use the JDBC-URL defined unless the environment variable DATABASE_URL_DB defines a value for it.
So you just set your development database in the configuration and for production or stages you define the environment variable.
But beware, this substitution does NOT WORK if you put your variable reference inside quoted strings:
db.default.url="jdbc:${?DATABASE_URL_DB}"
Instead, just unquote the section to be substituted, for example.
database_host = "localhost"
database_host = ${?ENV_DATABASE_HOST}
db.default.url="jdbc:mysql://"${?database_host}":3306/my-db-name"
In this example, localhost will be used by default if the environment variable ENV_DATABASE_HOST is not set. (For details see: https://www.playframework.com/documentation/2.5.x/ConfigFile#substitutions)
You can actually still use the Play 1.0 config value naming method, in Play 2, if you, when you load config values, check if Play.isTest, and then prefix the properties you load with 'test.'. Here's a snipped:
def configPrefix = if (play.api.Play.isTest) "test." else ""
def configStr(path: String) =
Play.configuration.getString(configPrefix + path) getOrElse
die(s"Config value missing: $configPrefix$path")
new RelDb(
server = configStr("pgsql.server"),
port = configStr("pgsql.port"),
database = configStr("pgsql.database"),
user = ...,
password = ...)
And the related config snippet:
pgsql.server="192.168.0.123"
pgsql.port="5432"
pgsql.database="prod"
...
test.pgsql.server="192.168.0.123"
test.pgsql.port="5432"
test.pgsql.database="test"
...
Now you don't need to remember setting any system properties when you run your e2e test suite, and you won't accidentally connect to the prod database.
I suppose that you can optionally place the test. values in a separate file, which you would then include at the end of the main config file I think.
There is another approach which is to override Global / GlobalSettings method onLoadConfig and from there you can setup application configuration with generic config and specific environment configuration like below...
conf/application.conf --> configurations common for all environment
conf/dev/application.conf --> configurations for development environment
conf/test/application.conf --> configurations for testing environment
conf/prod/application.conf --> configurations for production environment
You can check http://bit.ly/1AiZvX5 for my sample implementation.
Hope this helps.
Off-topic but if you follow 12-factor-app then having separate configurations named after environments is bad:
Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called “environments”) named after specific deploys, such as the development, test, and production environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as staging or qa. As the project grows further, developers may add their own special environments like joes-staging, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle
source: http://12factor.net/config

How does Google App Engine dev_appserver.py serve fresh content without restarting?

One of the things I like about Google App Engine development environment is, I don't have to restart the server every time I make changes to any python source files, other static files or even configuration files. It has spoilt me and I forget to restart the server when I am working with other server environments (tornadoweb, web.py, node.js).
Can anyone explain how GAE does that? How difficult is it to make other servers (at least python based) to achieve the same thing?
You can view the source for dev_appserver.py(link). Looks like ModuleManager makes a copy of sys.modules and monitors each module to track changes based on time:
class ModuleManager(object):
"""Manages loaded modules in the runtime.
Responsible for monitoring and reporting about file modification times.
Modules can be loaded from source or precompiled byte-code files. When a
file has source code, the ModuleManager monitors the modification time of
the source file even if the module itself is loaded from byte-code.
"""
http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/tools/dev_appserver.py#3636
Lot of webservers like GAE, make use of python reload module to see the effect in code change without restarting the server process
import something
if is_changed(something)
somthing = reload(something)
Quote from python docs:
When reload(module) is executed:
Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called a second time.
As with all other objects in Python the old objects are only reclaimed after their reference counts drop to zero.
The names in the module namespace are updated to point to any new or changed objects.
Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.

Resources