I know I can set this in the web.config but I want to set it conditionally depending on environment and add it to our core library. I have tried the below code but it does not work.
HttpCookiesSection cookieSection = (HttpCookiesSection)ConfigurationManager.GetSection("system.web/httpCookies");
cookieSection.HttpOnlyCookies = true;
cookieSection.RequireSSL = true;
The error is:
System.Configuration.ConfigurationErrorsException
The configuration is read only.
This kind of approach works fine for app settings. Note: I am not wanting to save the web.config, just change the setting in memory.
It appears from the documentation that this property is get-set.
From the docs:
// Set the RequireSSL.
httpCookiesSection.RequireSSL = false;
I´m searching for a logging framework for c# where I can set the logfile name easy from code.
My program starts several background workers which all should log into their own log files.
They use the same classes for their work and sometimes in different threads.
e.g.
backgroundworker1:
var aboImport = new CSVImport(file1); <-- logs into backgroundWorker1.log
aboImport.Execute();
ArchiveFile(file1);
backgroundworker2:
var addressImport = new CSVImport(file2); <-- logs into backgroundWorker2.log
addressImport.Execute();
ArchiveFile(file2);
e.g.
backgroundWorker1.log
backgroundWorker2.log
backgroundWorker3.log
...
heartbeat.log <-- I´can see my workers or main thread is running an working
I´m using using log4net at the moment, but this does not seem to fit my needs.
I found (Create multiple Logfiles with dynamic Names with log4net) where they create dynamic appenders in code.
But I do not understand whow this works, because the log4net definitions are normally tied to the namespaces.
Can other logging frameworks do this more elegant? Which logging framework do you recommend for this?
Stay away from Log4Net. It's not an actively developed project. Last release was almost 1 yr ago (12/2015). NLog is much better supported.
With that being said, all the logging frameworks let you do everything template driven with a bunch of different "macros"... you might base the filename on threadId or some other dynamic value... or just pass it in through a key/value pair. You have to look at all the "macros" available and pick the one that works in your scenario.
With nlog I could easy create loggers with different file targets.
private static void Main(string[] args)
{
var config = LogManager.Configuration;
AddLogger(config, "logger1", #"C:\Temp\Logfile\Log1.txt");
AddLogger(config, "logger2", #"C:\Temp\Logfile\Log2.txt");
LogManager.Configuration = config;
var logger1 = LogManager.GetLogger("logger1");
logger1.Debug("Test1");
var logger2 = LogManager.GetLogger("logger2");
logger2.Debug("Test2");
}
private static void AddLogger(LoggingConfiguration config, string loggerName, string fileName)
{
var fileTarget = new FileTarget();
config.AddTarget(loggerName, fileTarget);
fileTarget.FileName = fileName;
var rule = new LoggingRule(loggerName, LogLevel.Debug, fileTarget);
config.LoggingRules.Add(rule);
}
How can I temporarily disable logging of log4net based on the result of my function?
example:
if (MyCondition)
{
//Stop logging
}
else
{
//go on, log me...
}
i tried using these codes:
LogManager.GetRepository().Threshold = LogManager.GetRepository().LevelMap["OFF"];
LogManager.GetRepository().Threshold = LogManager.GetRepository().LevelMap["ALL"];
to try to disable log4net logging, but the results are the same. log4net is still logging.
Can this be done?
It might be easier to set the logging to "OFF" for all loggers at runtime, then switch them back on afterwards.
Some more info can be found here: http://geekswithblogs.net/rakker/archive/2007/08/22/114900.aspx
I'm facing currently a problem regarding Subsonic configuration.
What I want to achieve is using subsonic data access in a System.Web.UI.Design.ControlDesigner class.
This class is hosted in Visual Studio Environment and enables design time operations on the attached System.Web.UI.WebControls.Control.
The only problem is SubSonic seems always looking for SubSonicSection in the application configuration regardless passing connection string to it.
The relevant code snippet:
using (SharedDbConnectionScope dbScope = new SharedDbConnectionScope(new SqlDataProvider(), ConnectionString))
{
Table1 _table1 = new Select().From<..().Where(...).IsEqualTo(...).ExecuteSingle<...>();
Throws exception on ExecuteSingle() method (configuration section was not found)
while
using (SharedDbConnectionScope dbScope = new SharedDbConnectionScope(ConnectionString))
{
Throws exception on new SharedDbConnectionScope() (configuration section was not found)
So the question is:
Is there any way to pass the settings runtime to bypass the configuration section lookup as I don't want to add any subsonic specific configuration to devenv.configuration
Thanks
I don't think you can do this in 2.x without customising the templates (which can obviously give support issues when a newer version of SubSonic is released).
Sorry, don't know about 3.0
I'm assuming you're using SubSonic 2.x based on your query syntax. Have a look at the following two forum posts which should point you in the right direction. What you're trying to do is possible, in fact SubCommander does exactly this, download the source and have a look at the SetProviderManually() method.
http://forums.subsonicproject.com/forums/t/1617.aspx
http://forums.subsonicproject.com/forums/t/1502.aspx
The method to use Subsonic runtime provider configuration:
(example):
private void SetSubsonicProviderManually(string ConnectionString)
{
//clear the providers and reset
DataService.Provider = new SqlDataProvider();
DataService.Providers = new DataProviderCollection();
//instance a section - we'll set this manually for the DataService
SubSonicSection section = new SubSonicSection();
section.DefaultProvider = __SubsonicProviderName__;
//set the properties
DataProvider provider = DataService.Provider;
NameValueCollection config = new NameValueCollection();
//need to add this for now
config.Add("connectionStringName", __ConnectionString__);
//initialize the provider
provider.Initialize(__SubsonicProviderName__, config);
provider.DefaultConnectionString = ConnectionString;
DataService.Providers.Add(provider);
}
Has anyone got this working in a web application?
No matter what I do it seems that my appSettings section (redirected from web.config using appSettings file=".\Site\site.config") does not get reloaded.
Am I doomed to the case of having to just restart the application? I was hoping this method would lead me to a more performant solution.
Update:
By 'reloading' I mean refreshing ConfigurationManager.AppSettings without having to completely restart my ASP.NET application and having to incur the usual startup latency.
Make sure you are passing the correct case sensitive value to RefreshSection, i.e.
ConfigurationManager.RefreshSection("appSettings");
This seems to be a flaw (maybe a bug) when using an external config file for your appSettings. I've tried it using the configSource attribute and RefreshSection simply never works, I'm assuming this is the same when using the file attribute.
If you move your appSettings back inside your web.config RefreshSection will work perfectly but otherwise I'm afraid you're doomed.
For some reason ConfigurationManager.RefreshSection("appSettings") wasn't working for me. Reloading the Web.Config into a Configuration object seems to work correctly. The following code assumes the Web.Config file is one directory below the executing (bin) folder.
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
Uri uriAssemblyFolder = new Uri(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
string appPath = uriAssemblyFolder.LocalPath;
configMap.ExeConfigFilename = appPath + #"\..\" + "Web.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
And is used like:
string webConfigVariable = config.AppSettings.Settings["webConfigVariable"].Value;
.RefreshSection() does not work when the appSettings is external.
You can however use the following to change a value:
ConfigurationManager.AppSettings.Set(key, value)
This will NOT change the setting on file, only the loaded value in memory.
So instead of using RefreshSection I did the following:
string configFile="path to your config file";
XmlDocument xml = new XmlDocument();
xml.Load(configFile);
foreach (XmlNode node in xml.SelectNodes("/appSettings/add"))
{
string key = node.Attributes["key"].Value;
string value= node.Attributes["value"].Value;
ConfigurationManager.AppSettings.Set(key, value);
}
Any subsequent calls to AppSettings.Get will contain the updated value.
The appSettings will then be updated without needing to restart the application.
As an alternative you could write your own ConfigSection and set restartOnExternalChanges="false".
Then, when reading the section with ConfigurationManager.GetSection("yourSection") the settings will be auto-refreshed without an application restart.
And you could implement your settings strongly typed or as NameValueCollection.
Yes. you are stuck with iis restarting.
There is a feature with asp.net 4.0 and iis 7.5 where the initial startup is removed.
I am not sure if this is possible in a web app, but it works in a desktop app. Try using ConfigurationSettings rather than ConfigurationManager (it will yell at you for using outdated classes...), then reading all the data into a class. When you wish to refresh, simply create a new instance and drop all references to the old instance. My theory for why this works (might be wrong): when you don't directly access the app.config file the entire time you are running, the file lock is dropped by the application. Then, edits can be made when you are not accessing the file.
The App.Config settings are cached in memory when the application starts. For this reason, I don't think you'll be able to change those settings without restarting your application. One alternative that should be pretty straight forward would be to create a separate, simple XML configuration file, and handle loading/caching/reloading it yourself.
To write, call it this way:
Dim config As System.Configuration.Configuration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~")
Return AddOrUpdateAppSetting(config, "YourSettingKey", "YourValueForTheKey")
To read and be sure you get the values in file, instead of those in cache, read it this way:
Dim config As System.Configuration.Configuration = WebConfigurationManager.OpenWebConfiguration("~")
Return config.AppSettings.Settings("TheKeyYouWantTheValue").Value
Full example:
Protected Shared Function AddOrUpdateAppSetting( _
ByVal Config As System.Configuration.Configuration _
, ByVal TheKey As String _
, ByVal TheValue As String _
) As Boolean</p>
Dim retval As Boolean = True
Dim Itm As System.Configuration.KeyValueConfigurationElement = _
Config.AppSettings.Settings.Item(TheKey)
If Itm Is Nothing Then
If Config.AppSettings.Settings.IsReadOnly Then
retval = False
Else
Config.AppSettings.Settings.Add(TheKey, TheValue)
End If
Else
' config.AppSettings.Settings(thekey).Value = thevalue
If Itm.IsReadOnly Then
retval = False
Else
Itm.Value = TheValue
End If
End If
If retval Then
Try
Config.Save(ConfigurationSaveMode.Modified)
Catch ex As Exception
retval = False
End Try
End If
Return retval
End Function
Have you tried storing your AppSettings in its own external file?
From app.config/web.config:
<appSettings configSource="appSettings.config"></appSettings>
appSettings.config:
<?xml version="1.0"?>
<appSettings>
<add key="SomeKey" value="SomeValue" />
</appSettings>
Changes made to appSettings.config should be reflected instantly.
More info:
http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx