I have been asked to create a visual contrast for an HTML form to distinguish it from a production environment and a development environment, using a web.config file.
My exposure to ASP.NET is very limited. Although I've been researching web.config files since yesterday, due to my lack of experience in this technology, I still don't think I can provide a solid solution with much confidence.
If this job could be handled directly with HTML, CSS, PHP or JS I could do it myself, but using web.config is a requirement.
The goal is to create an unmistakable visual change (let's say, lightgreen background) when a user is on the development form.
There is already a CSS stylesheet in play, so I'm thinking the change would have to go inline in the HTML to override the external styles.
So here's the question, if it makes any sense:
If this is in the production web.config: <add key="CurEnv" value="Production"/> and this is in dev: <add key="CurEnv" value="Development"/>, how can I set the form's background color based on the value in the config file?
This is how I do it:
For DEV, for example, I have the following key in my appSettings:
<appSettings>
<add key="skin" value="skin-gray"/>
...
</appSettings>
And then in my Master page (if using Web Forms) or on my _Layout.cshtml (if using MVC), I have the following HTML:
<body class="#System.Configuration.ConfigurationManager.AppSettings["skin"]">
The syntax for WebForms would be:
<body class="<%=System.Configuration.ConfigurationManager.AppSettings["skin"]%>">
For Production, I have a "skin-blue" setting in my appSettings section and that way, when I deploy the app, depending on the environment, the skin is automatically changed.
I actually do this automatically, as part of the Build process using Slow Cheetah
So that depending on which Configuration is chosen to build the application, the right value is used. This is my transform for Web.Production.Config:
<appSettings>
<add key="skin" value="skin-blue" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
</appSettings>
I think you can read those link. It's may help you:
http://forums.asp.net/t/1349824.aspx?How+to+set+CSS+color+settings+from+web+config
Dynamically setting CSS values using ASP.NET
Related
Is there a way to get a web.config transformation in Visual Studio 2015+ to include the contents of an externally-referenced secrets file as described here?
This works well when developing locally, and doesn't include the file in source control, but when I go to deploy the web app to the server, I want it to include the username and password for another web service which it connects to. If I enter the settings manually in IIS on the server, they are lost each time I publish the app.
If I omit the keys in the appSettings block in my web.config (so that they are only referred to in the secrets file), the manually-entered settings in IIS on the server are removed completely whenever I publish the app.
Being able to refer to certain things in an external file for the sake of better security and not checking in passwords to source control isn't turning out to be a very good idea IMHO because my deployment is now a nightmare. I don't want to manually enter the passwords in the web.config file on the server after every deployment.
I'd rather not look into encryption, either, because I would have to do that for each server I deploy to so that the relevant machine key is used for each web.config file.
I've only recently thought about removing this password from source control, in response to a recent push to improve security practises at work - which I well understand and agree with - but I can also see why security is so poorly considered because the life of the ordinary developer becomes extremely unpleasant if there the tools available don't make it easy.
Surely there's a way without resorting to encryption?
Thanks.
Without a CI system I think your best option is probably a pre/post build action that executes a script?
I'd suggest you replace the actual values with tokens for your sensitive web.config values (something unique/easy to find like MY_PRODUCT_DATABASE_PASSWORD etc). Your web.config can then be checked into source control safely.
In VS you can add a build action to run a custom powershell or exe to basically perform a find-and-replace on the tokens with actual values before you zip & deploy as normal.
Exactly how/where you store the real values and how the script works is up to you. you could easily find a file on your deployment machine or a row in some database based on data passed to the script/exe from vs or from data within web.config itself (or embedded as a comment in web.config even).
Here's details of the variables available from vs you could pass to your exe or script in a build action: https://msdn.microsoft.com/en-us/library/42x5kfw4.aspx
It you wanted to use PowerShell you could read/replace/write values to a web.config(or any text file) like this answer: How can I replace every occurrence of a String in a file with PowerShell?
Following the Microsoft Docs example you've linked to, putting this XDT transformation inside Web.Release.config should do the trick:
<appSettings file="..\..\AppSettingsSecrets.config" xdt:Transform="SetAttributes">
<add key="mailAccount" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="mailPassword" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioSid" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioToken" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioFromPhone" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="GoogClientID" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="GoogClientSecret" xdt:Locator="Match(key)" xdt:Transform="Remove" />
</appSettings>
You dont need xdt:Locator attribute on <appSettings> element itself, because there is only one appSettings.
Edit: I've misunderstood the original question. The goal is to include contents of referenced file, which is not possible using XDT. There has to be another way.
Consider a group of developers working on an ASP.net web application. Each developer would like to have a private version of the web.config.
By "private" I mean that a developer can freely change the file to suit their dev/test needs at any given moment, without it affecting other team members and without ending up in source control.
How can one go about achieving this with Visual Studio 2015?
My closest solution so far is to have a "private" Solution Configuration with a matching Web.config Transformation file ("web.private.config") that's excluded from source control.
But this is not a satisfactory solution because:
a. The transformation is not run automatically when debugging (with F5). The developers need to remember to run it manually.
b. The result of the transformation ends up in the main "web.config" file which is, naturally, included in source control.
We had a very similar problem but only needed personalized versions of the <appSettings> section in Web.config.
In this situation the inclusion of an external file through configSource turned out to be problematic, as this attribute completely replaces the <appSettings>-node. So there remains no way to keep global key/values AND personal key/values for all developers. The whole section is completely replaced by the included private file.
What we need is both global and private <appSettings>. The solution we found was the file attribute. It allows to merge Web.config settings with settings from an additional file.
We ended up with a construct like this one:
<!-- Web.config with global appSettings) -->
...
<appSettings file="Web.PERSONAL.config">
<add key="BaseUrl" value="https://projectname.dev.local" />
...
</appSettings>
...
<!-- Web.PERSONAL.config with personal appSettings -->
<?xml version="1.0" encoding="utf-8"?>
<appSettings >
<add key="EmailSmtpUser" value="my.name#my.domain.com" />
<add key="EmailSmtpPwd" value="***" />
</appSettings >
If you put identical keys in both files, the Web.PERSONAL.config version will overwrite the Web.config version.
The file Web.PERSONAL.config must be excluded from Git through .gitignore .
Keep in mind:
While configSource works for ALL nodes in Web.config, the file attribute is restricted to <appSettings>.
Have web.config include an external file (via configSource) and add that file to .gitignore
The correct answer is to host your local development site in a separate location from your Visual Studio solution. You can then use publish profiles to publish changes to that location and web.config transforms to maintain a separate local config for each developer. Each developer would use a different publish profile which transforms the web.config with their own transform and deploys the transformed web.config to the publish location. You can then attach a debugger to the published site using Visual Studio's Debug > Attach To Process option.
I think there is a lot of value in standardising dev environments so that one can just download the solution and run it.
Custom, long term/permanent, developer specific configs will sooner or later lead to a subtle bug that will be tricky to find.
My solution to your problem would be to find out the reason(s) why permanent individual configs are needed and have a look if these environment specific differences can be eliminated.
is it possible to set a default page to run when starting debugging? In Visual Studio you can set the default page either through the context menu in Solution Explorer or in the project properties. I did not find something like that in MonoDevelop.
When I am starting debugging the browser will always navigate to the root of the application.
http://localhost:8080
Because there is no default page set in XSP for this application I get an error and always have to correct it manually.
http://localhost:8080/home.aspx
Thanks for your help.
I found a solution. I did not find the xsp.exe.config but it also works when you add the setting either globally in machine.config (residing in /etc/mono/[version]) or by creating a web.config file in your applications root. The values are comma separated.
<appSettings>
<add key="MonoServerDefaultIndexFiles" value="Home.aspx, home.aspx" />
</appSettings>
The help page http://www.mono-project.com/Config does not tell you that a appSettings section is allowed, but I think that the documentation is just incomplete. For example appSettings are used here http://www.mono-project.com/ASP.NET_Settings_Mapping#Inhibiting_the_settings_mapping too.
I am trying to update the configSource attribute on the appSettings element within my web.config file using web.config transformations.
I have the following in my web.config
<appSettings configSource="Config\appSettings.local.config">
</appSettings>
I want this to be
<appSettings configSource="Config\appSettings.prod.config">
</appSettings>
when i build Release. This is not happening. I have the following in my Web.Release.config in the element
<appSettings xdt:Transform="SetAttributes(configSource)" configSource="Config\appSettings.prod.config" />
Transformations only happen when you deploy the web application (or create a deployment package). It does not happen when you simply build the solution.
http://msdn.microsoft.com/en-us/library/dd465326.aspx
"For Web application projects, ASP.NET provides tools that automate the process of changing (transforming) Web.config files when they are deployed."
You can cause the transformation to happen on build if you like though, with a little poking around in your project file. I wrote a post on this a while back, its centered on app.config but it will work for web.config you can just miss a few steps out!
http://www.chrissurfleet.co.uk/post/2011/07/27/Faking-Webconfig-transformations-in-appConfig.aspx
if it is cached, what happens if I use multiple web.config in multi-level folders
They all get cached.
Configuration is read once, at startup. With web.config, IIS watches for file changes and restarts the application.
OK, so ya'll are missing a KEY feature in the Web.Config file's area.
Yes, web.config is cached and changing contents of the file will restart your web app. And, all your connected users will not be happy, too, because they'll need to "reconnect" a-new, possibly losing desired information.
So, use an EXTERNAL custom file for your AppSettings, as follows:
<appSettings configSource="MyCustom_AppSettings.config"/>
Then, in the file MyCustom_AppSettings.config file, you have your settings, as such this example has:
<appSettings>
<!-- AppSecurity Settings -->
<add key="AppStatus_Active" value="Active"/>
<!-- Application Info Settings -->
<add key="AppID" value="25"/>
<add key="AppName" value="MyCoolApp"/>
<add key="AppVersion" value="20120307_162344"/>
</appSettings>
Now, if you need to add, change, or remove an AppSetting, when you change it in this file the change is nearly instant in your web-app BUT (and here's the BEST part), your app DOES NOT RESTART!
Everything stays kosher except those settings you've added/modified/removed in the external .config file.
And, yes, the same thing can done for the section as follows:
<connectionStrings configSource="MyCustomApp_ConnectionStrings.config"/>
and the file MyCustomApp_ConnectionStrings.config has all the connection strings you need. Change a connection string in the external .config file and it starts getting used right away and with no web-app restart.
The configSource setting(s) are great when you need to deploy to development, testing, and production on different boxes and need settings pertinent to that given box/environment.
So, now ya know (something that's been around for 7+ years).
It's That Simple. Really.
KC
Web.config (excluding external config files) is read when the application loads. Some config settings have a cascading behavior. For example, the system.web/authorization section can be overridden by configs at deeper levels.
ASP.NET monitors the web.config for changes. When it changes, the web application is forced to restart. Moral is that web.config settings are cached for the life of the application.