Can I have different '.settings' specified for debug and release configurations? - configuration

I have a .settings file (containing both User and Application settings) that I would like to contain different values if built in Debug mode. Is there a supported or recommended way to do this?

I use two separate config files for each mode. I copy the files into the BIN folder in the POST-BUILD event.

The Settings.Designer.cs file doesn't contain values, only application setting property declarations. The values are stored separately. Application setting values go into the app.exe.config file, user scoped setting values go in an appdata folder that has a name generated by a hashing algorithm. You'd only have trouble with the latter. Shouldn't matter, the file won't exist when you deploy your Release build to a machine.
In case you mean "can I change the default value" then the answer is: not when you use the settings designer. You'll have to move the setting into a separate class. Make it look similar to this:
using System;
using System.Configuration;
using System.Diagnostics;
namespace ConsoleApplication1.Properties {
internal partial class Settings {
[UserScopedSetting, DebuggerNonUserCode]
#if DEBUG
[DefaultSettingValue("debug value")]
#else
[DefaultSettingValue("release value")]
#endif
public string Setting {
get {
return ((string)(this["Setting"]));
}
set {
this["Setting"] = value;
}
}
}
}
Make sure the namespace name matches the one used in the Settings.Designer.cs file and that you delete the setting from the Settings page.

Related

Can you preview ASP.NET Core's appsettings.json environment overrides?

In ASP.NET Core, the JsonConfigurationProvider will load configuration from appsettings.json, and then will read in the environment version, appsettings.{Environment}.json, based on what IHostingEnvironment.EnvironmentName is. The environment version can override the values of the base appsettings.json.
Is there any reasonable way to preview what the resulting overridden configuration looks like?
Obviously, you could write unit tests that explicitly test that elements are overridden to your expectations, but that would be a very laborious workaround with upkeep for every time you change a setting. It's not a good solution if you just wanted to validate that you didn't misplace a bracket or misspell an element name.
Back in ASP.NET's web.config transforms, you could simply right-click on a transform in Visual Studio and choose "Preview Transform". There are also many other ways to preview an XSLT transform outside of Visual Studio. Even for web.config parameterization with Parameters.xml, you could at least execute Web Deploy and review the resulting web.config to make sure it came out right.
There does not seem to be any built-in way to preview appsettings.{Environment}.json's effects on the base file in Visual Studio. I haven't been able to find anything outside of VS to help with this either. JSON overriding doesn't appear to be all that commonplace, even though it is now an integral part of ASP.NET Core.
I've figured out you can achieve a preview with Json.NET's Merge function after loading the appsettings files into JObjects.
Here's a simple console app demonstrating this. Provide it the path to where your appsettings files are and it will emit previews of how they'll look in each environment.
static void Main(string[] args)
{
string targetPath = #"C:\path\to\my\app";
// Parse appsettings.json
var baseConfig = ParseAppSettings($#"{targetPath}\appsettings.json");
// Find all appsettings.{env}.json's
var regex = new Regex(#"appsettings\..+\.json");
var environmentConfigs = Directory.GetFiles(targetPath, "*.json")
.Where(path => regex.IsMatch(path));
foreach (var env in environmentConfigs)
{
// Parse appsettings.{env}.json
var transform = ParseAppSettings(env);
// Clone baseConfig since Merge is a void operation
var result = (JObject)baseConfig.DeepClone();
// Merge the two, making sure to overwrite arrays
result.Merge(transform, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace
});
// Write the preview to file
string dest = $#"{targetPath}\preview-{Path.GetFileName(env)}";
File.WriteAllText(dest, result.ToString());
}
}
private static JObject ParseAppSettings(string path)
=> JObject.Load(new JsonTextReader(new StreamReader(path)));
While this is no guarantee there won't be some other config source won't override these once deployed, this will at least let you validate that the interactions between these two files will be handled correctly.
There's not really a way to do that, but I think a bit about how this actually works would help you understand why.
With config transforms, there was literal file modification, so it's easy enough to "preview" that, showing the resulting file. The config system in ASP.NET Core is completely different.
It's basically just a dictionary. During startup, each registered configuration provider is run in the order it was registered. The provider reads its configuration source, whether that be a JSON file, system environment variables, command line arguments, etc. and builds key-value pairs, which are then added to the main configuration "dictionary". An "override", such as appsettings.{environment}.json, is really just another JSON provider registered after the appsettings.json provider, which obviously uses a different source (JSON file). Since it's registered after, when an existing key is encountered, its value is overwritten, as is typical for anything being added to a dictionary.
In other words, the "preview" would be completed configuration object (dictionary), which is composed of a number of different sources, not just these JSON files, and things like environment variables or command line arguments will override even the environment-specific JSON (since they're registered after that), so you still wouldn't technically know the the environment-specific JSON applied or not, because the value could be coming from another source that overrode that.
You can use the GetDebugView extension method on the IConfigurationRoot with something like
app.UseEndpoints(endpoints =>
{
if(env.IsDevelopment())
{
endpoints.MapGet("/config", ctx =>
{
var config = (Configuration as IConfigurationRoot).GetDebugView();
return ctx.Response.WriteAsync(config);
});
}
});
However, doing this can impose security risks, as it'll expose all your configuration like connection strings so you should enable this only in development.
You can refer to this article by Andrew Lock to understand how it works: https://andrewlock.net/debugging-configuration-values-in-aspnetcore/

Moving Sitemesh3.xml to a different folder

I'm practicing web programming by using Spring 3.1, Hibernate and SiteMesh3.
I want to move 'sitemesh3.xml' file to other directory as WEB-INF/spring/ (not in WEB-INF directly). I've tried it, but sitemesh didn't work. Is it possible to move it? If it is, what properties, if any, should I add on other files like web.xml?
(I've read http://wiki.sitemesh.org/wiki/display/sitemesh3/Configuring+SiteMesh+3, which says "The configuration file should live in /WEB-INF/sitemesh3.xml in your web-application.")
Consider using java config, you can get rid of xml configuration totally.
Follow Sitemesh Java Config
Create a filter like this and register it in your web.xml or in java configuration file.
#WebFilter(urlPatterns = "/*")
public class ConfiguredSiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/WEB-INF/decorators/defaultDecorator.jsp");
}
}

How to pass configuration parameters to SimpleInjector packaging?

So SimpleInjector now has a packaging nuget that you can use to isolate different aspects of root composition.
Say I have a configurable composition root in a library that is reused by multiple projects in an application. For example, in an Azure solution I might have a Web role and a Worker role which share a large set of the same dependencies for the most part, but with slightly different configuration options depending on the consumer. When I compose the root, I can pass in a plain old RootCompositionSettings object with properties that tell SimpleInjector how to register dependencies.
However, I am not sure how (or if) I can pass these settings to an IPackage instance. Is it possible to pass custom settings to a SimpleInjector package, and if so, how?
I see that the standard practices for registering packages is to invoke either
container.RegisterPackages(); // scans all loaded assemblies for IPackage
// or
container.RegisterPackages(IEnumerable<Assembly>) // specific assemblies only
...so how can we pass parameters into the packaging instance(s)? Is there some way to do it via the container?
The trick here is to pass the information on with the container to the package. You can do this by using the container's Items dictionary, that is much like ASP.NET's HttpContext.Items collection. This can be done as follows:
using SimpleInjector.Advanced;
container.SetItem(typeof(RootCompositionSettings), settings);
container.RegisterPackages();
Now inside your packages, you can do the following:
var settings =
(RootCompositionSettings)container.GetItem(typeof(RootCompositionSettings));
Please note that:
SetItem and GetItem are extension methods that are located in the SimpleInjector.Advanced namespace. Those methods allow you to access the (internal) Items dictionary.
You can pass in any key you like. Passing in typeof(RootCompositionSettings) is just convenient in this case, but not required.
If you need to call the settings in more places, it might be useful to create a more specific extension method that allows you to access the setting instance, but that's up to you.
Another option is to not use the IPackage interface and the SimpleInjector.Packaging library at all. In most cases it doesn't really add anything and you could simply define a public static method in the assembly that does the same as a package does. For instance:
public static class BusinessLayerBootstrapper
{
public static void Bootstrap(Container container, ScopedLifestyle scopedLifestyle,
RootCompositionSettings settings)
{
// Here the same logic as what you would write in your package.
}
}
Most applications are not that dynamic that you need to load assemblies dynamically and the startup project usually has a hard reference to all the other assemblies. In that case it is perfectly sane to simply call a static method.
And even if you have the requirement of dynamically loading assemblies and allowing them to register their stuff in the container, it's quite trivial to build your own IPackage abstraction instead:\
// Your own IPackage interface
public interface IPackage
{
void RegisterServices(Container container, RootCompositionSettings settings);
}
// Your own extension method
public static void RegisterPackages(this Container container,
RootCompositionSettings settings)
{
var packages =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetExportedTypes()
where typeof(IPackage).IsAssignableFrom(type)
where !type.IsAbstract
select (IPackage)Activator.CreateInstance(type);
packages.ToList().ForEach(p => p.RegisterServices(container, settings));
}
In fact, except for some extra validations and filtering out dynamic assemblies, the SimpleInjector.Packaging project is not much more than this.

How to stop Flash Builder from caching Compiler config files specified by -load-config

Every time I try to change a compiler constant, it seems I HAVE to:
Do a Project -> Clean.
Close Flash Builder.
Wait for it to fully close (does it's Workspace save thing...)
Re-Launch Flash Builder (and again, wait for it to finish loading...)
Re-Build All (got 3 projects dependent of eachother).
Test Run/Debug it (or Export a Release version).
This is extremely annoying and time-consuming. Is there a setting somewhere I can set so that Flash Builder ALWAYS reads the latest changes in the custom Compiler config.xml file I've made?
It basically contains something like this:
Changes to something as simple as the Version # becomes a long process.
Any workarounds?
I'm not a Flash Builder user, so take this with a pinch of salt. Some possible workarounds:
Define your constants in the project itself
Your problem seems to be that Flash Builder isn't picking up changes in an external file - from some quick searching on google, it seems to be a pretty common problem with no particular solution other than what you're doing (or going back to 4.6).
To declare your consts in the project itself, go to Project Settings > ActionScript Compiler and under Additional Compiler Arguments add your constants like so:
-define+=COMPILE::LANG_EN,true
-define+=COMPILE::LANG_FR,false
...
Each one needs to be on a separate line, and you might need to replace COMPILE with CONFIG (the default)
Build your project using ANT
It can be a bit of a pain to set up, but once it's done, you should be fine. You should be able to declare them like so:
<mxmlc ... >
<define name="CONFIG::LANG_EN" value="true"/>
<define name="CONFIG::LANG_FR" value="false"/>
</mxmlc>
Taken from http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7abd.html
Define your constants in code
It's possible to define compile constants directly in code, though it only works for the block of code it's declared in (e.g. class level). Depending on what you need it for (i.e. if you're setting up different values vs actually removing code), this could do what you need (e.g. set it up on a constants class, to set the value of different constants depending on the compile const. Then use those constants throughout your code)
package
{
config namespace COMPILE;
COMPILE const LANG_EN = true;
COMPILE const LANG_FR = !COMPILE::LANG_EN;
public class MyClass
{
public function MyClass()
{
this.sayHello();
}
COMPILE::LANG_EN
public function sayHello():void
{
trace("hello");
}
COMPILE::LANG_FR
public function sayHello():void
{
trace("bonjour");
}
public function foo():void
{
COMPILE::LANG_EN { trace( "foo" ); }
COMPILE::LANG_FR { trace( "bar" ); }
}
}
}
Change IDE
FlashDevelop can be your friend here. In the office, I work on FlashDevelop, and some of the other devs work using FlashBuilder. Each has their own strong points.
We use compiler constants defined using the first method for situations where blocks of code need to be removed (i.e. supporting mobile and web builds), and we use an embedded XML for other "constants" depending on the build; version, server ip, api keys, etc. Which XML gets embedded in the case of the latter depends on a single compiler const.

Monodroid: Where should I put configuration settings?

From Miguel de Icaza:
We use a library profile that is better suited for mobile devices, so we removed features that are not necessary (like the entire System.Configuration stack, just like Silverlight does).
After years of .NET development, I'm accustomed to storing configuration settings in web.config and app.config files.
When using Mono for Android, where should I put my configuration settings?
If it matters, I'd like to store different configuration settings for different build configurations as well.
I would probably recommend using shared preferences and compilation symbols to manage different configurations. Below is an example of how you can use a preferences file to add or change keys based on the compilation symbols. Additionally, you could create a separate preferences file that is only available for a particular configuration. Because these keys are not available on all configurations, make sure to always perform checks for them before using.
var prefs = this.GetSharedPreferences("Config File Name", FileCreationMode.Private);
var editor = prefs.Edit();
#if MonoRelease
editor.PutString("MyKey", "My Release Value");
editor.PutString("ReleaseKey", "My Release Value");
#else
editor.PutString("MyKey", "My Debug Value");
editor.PutString("DebugKey", "My Debug Value");
#endif
editor.PutString("CommonKey", "Common Value");
editor.Commit();
We have had exactly the same problem in our current project.
My first impulse was to put the configuration in a sqlite key-value table but then my internal customer reminded me the main reason for a configuration file - it should support simple editing.
So instead we created an XML file and put it there:
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
And access it using these properties:
public string this[string key]
{
get
{
var document = XDocument.Load(ConfigurationFilePath);
var values = from n in document.Root.Elements()
where n.Name == key
select n.Value;
if(values.Any())
{
return values.First();
}
return null;
}
set
{
var document = XDocument.Load(ConfigurationFilePath);
var values = from n in document.Root.Elements()
where n.Name == key
select n;
if(values.Any())
{
values.First().Value = value;
}
else
{
document.Root.Add(new XElement(key, value));
}
document.Save(ConfigurationFilePath);
}
}
}
via a singleton class we call Configuration so for .NET developers it is very similar to using the app.config files. Might not be the most efficient solution but it gets the job done.
there's a Xamarin centric AppSetting reader: https://www.nuget.org/packages/PCLAppConfig
pretty useful for continuous delivery (so a deployment server such as octopus allows to alter your config file for each environment with values stored on the cd server)
there's a Xamarin centric AppSetting reader available at https://www.nuget.org/packages/PCLAppConfig
it is pretty useful for continuous delivery;
use as per below:
1) Add the nuget package reference to your pcl and platforms projects.
2) Add a app.config file on your PCL project, then as a linked file on all your platform projects. For android, make sure to set the build action to 'AndroidAsset', for UWP set the build action to 'Content'. Add you settings keys/values: <add key="config.text" value="hello from app.settings!" />
3) Initialize the ConfigurationManager.AppSettings on each of your platform project, just after the 'Xamarin.Forms.Forms.Init' statement, that's on AppDelegate in iOS, MainActivity.cs in Android, App in UWP/Windows 8.1/WP 8.1:
ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
3) Read your settings : ConfigurationManager.AppSettings["config.text"];
ITNOA
Maybe PCLAppConfig is help you to create and read from app.config in Xamarin.Forms PCL Project or other Xamarin projects.
For different configuration in different build mode such as release and debug you can use Configuration Transform on app.config.