Reading from app.config yields null results - c#

My issue is as the title reads, when I attempt to get some app settings for a given key, I am always returned with null.
I have 2 projects, 1 .Net Core Class library and 1 .Net Core Test Solution. Both contain an identical app.config.
https://imgur.com/a/oD8FHPW.
Here is the solution explorer so you can see the project set up.
In my tests solution, I am trying to test the validity of my helper using this test method
[TestMethod]
public void TestSaveLocationHelper()
{
ConfigurationResponseMessage connectionString = ConfigurationHelper.GetSaveLocation();
Assert.IsTrue(connectionString.ResponseCode == ResponseCode.SUCCESS);
}
I wrote a helper method that calls the configurationManager.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
namespace Unity.Helpers
{
public static class ConfigurationHelper
{
public static ConfigurationResponseMessage GetSaveLocation()
{
string saveLocation = ConfigurationManager.AppSettings[Constants.SAVE_LOCATION];
if (!string.IsNullOrWhiteSpace(saveLocation))
return new ConfigurationResponseMessage()
{
ConfigString = saveLocation,
ResponseCode = ResponseCode.SUCCESS
};
return new ConfigurationResponseMessage()
{
ConfigString = string.Empty,
ResponseCode = ResponseCode.FAILURE
};
}
}
}
saveLcoation is always null
Constants.SAVE_LOCATION = 'SaveLocation'
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SaveLocation" value="D:/test.json"/>
</appSettings>
</configuration>
Not entirely sure what is wrong. Thanks for any help

Related

How to add Global MongoDB connection String to C# Project

I am using my MongoDB database to store some documents for my project. The driver version for MongoDB I am using is 2.12.2.
How I am using my Mongo connection for my Operations is like this,
Web.config
<configuration>
<appSettings>
<add key="MongoDBDatabase" value="TestDB" />
</appSettings>
<connectionStrings>
<add name="MongoConnection" connectionString="myconnnection/db?retryWrites=true"/>
</connectionStrings>
</configuration>
DBConnection.cs
using System.Configuration;
namespace MyProj.DataAccess.Implementations
{
internal class DBConnection
{
public static string MongoDBConnectionString { get { return ConfigurationManager.ConnectionStrings["MongoConnection"].ConnectionString; } }
public static string MongoDBdatabase { get { return ConfigurationManager.AppSettings["MongoDBDatabase"].ToString(); } }
}
}
UserDAL.cs
namespace MyProj.DataAccess.Implementations
{
public class UserDAL: IUserDAL
{
public static string database = DBConnection.MongoDBdatabase;
public List<UserTbl> GetAll()
{
var con = new MongoClient(DBConnection.MongoDBConnectionString);
var db = con.GetDatabase(database);
var collection = db.GetCollection<UserTbl>("UserTbls");
var users=collection.AsQueryable().ToList();
}
}
}
The thing is I need to call the connection globally like from singleton. So that only a single connection is open for multiple requests. How can I do that ?
I prefer to you to config your mongodb client with best practices like this
you can define your mongodb as singlton but be aware you should use async methods , I prefer you to use ConcurrentQueue and its methods

How can we resolve dependency with configuration file settings

I am kind of new to the dependency injection resolver techniques topic. May I know how we can resolve dependency through configuration file section(s)? Below are my classes and interface along with the config file.
I am sure that missing some portion of code/setting. Can you please help me with this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UnityConfiguration_Testing
{
public interface IUserAuthentication
{
string Authenticate(string username, string password);
string GetUserRole(string username);
}
}
public class CloudAppAuthetication: IUserAuthentication
{
public string Authenticate(string username, string password)
{
return "This Authenticate method executed from cloud class";//Jwt token based authentication logic should be there
}
public string GetUserRole(string username)
{
return "This GetUserRole method executed from cloud class";//New logic to user management api call
}
}
public class StandaloneAppAuthetication : IUserAuthentication
{
public string Authenticate(string username, string password)
{
return "This Authenticate method executed from standalone class";//current logic should be here
}
public string GetUserRole(string username)
{
return "This GetUserRole method executed from standalone class";//current logic should be here
}
}
Console application calling of interface method:
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UnityConfiguration_Testing
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.LoadConfiguration("TestContainer");
IUserAuthentication _userAuthentication = null;
string validatedUser = _userAuthentication.Authenticate("testuser#user.com", "testpassword");
string validatedUserRole = _userAuthentication.GetUserRole("testuser#user.com");
}
}
}
My App.config file of console application is:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container name="TestContainer">
<register type="UnityConfiguration_Testing.IUserAuthentication,UnityConfiguration_Testing" mapTo="UnityConfiguration_Testing.StandaloneAppAuthetication,UnityConfiguration_Testing" />
</container>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
Inversion Of Control contener is what you want to have.
There are many. For example Autofac. They have ability to register implementations for interface depending on your configuration in config files or you can configure it at runtime.
If I understood the question correctly, this is roughly what you're looking for.
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
Type t = Type.GetType("Second"); //get class name from config here
MethodInfo method
= t.GetMethod("Hello", BindingFlags.Static | BindingFlags.Public); // get method by name here
Console.WriteLine(method.Invoke(null,null));
}
}
public static class First
{
public static string Hello(){
return "hello";
}
}
public static class Second
{
public static string Hello(){
return "Hello World";
}
}
This will allow you to get a class and method defined by names you can get from the config file.

Create custom section in config file

I am trying to create custom section in app.config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="BlogSettings" type="ConsoleApplication1.BlogSettings,
ConsoleApplication1" />
</configSections>
<BlogSettings
Price="10"
title="BLACKswastik" />
</configuration>
C# code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string title = BlogSettings.Settings.Title;
Console.WriteLine(title);
Console.ReadKey();
}
}
public class BlogSettings : ConfigurationSection
{
private static BlogSettings settings
= ConfigurationManager.GetSection("BlogSettings") as BlogSettings;
public static BlogSettings Settings
{
get
{
return settings;
}
}
[ConfigurationProperty("Price"
, DefaultValue = 20
, IsRequired = false)]
[IntegerValidator(MinValue = 1
, MaxValue = 100)]
public int Price
{
get { return (int)this["Price"]; }
set { this["Price"] = value; }
}
[ConfigurationProperty("title"
, IsRequired = true)]
[StringValidator(InvalidCharacters = " ~!##$%^&*()[]{}/;’\"|\\"
, MinLength = 1
, MaxLength = 256)]
public string Title
{
get { return (string)this["title"]; }
set { this["title"] = value; }
}
}
}
but when I run this code I am getting this error:
The type initializer for 'ConsoleApplication1.BlogSettings' threw an
exception.
Please suggest me whats wrong I am doing.
You should check out Jon Rista's three-part series on .NET 2.0 configuration up on CodeProject.
Unraveling the mysteries of .NET 2.0 configuration
Decoding the mysteries of .NET 2.0 configuration
Cracking the mysteries of .NET 2.0 configuration
Highly recommended, well written and extremely helpful! This will give you a thorough understanding of the .NET configuration system.
Phil Haack also has a great blog post Three easy steps to a custom configuration section that will give you a quick head-start into building your own custom config sections.
To design your own custom section, there's also a handy tool (Visual Studio add-in) called Configuration Section Designer that will make it very easy and simple to create your own custom section and have it build up all the necessary code to handle that custom section.
move this out of the config section
<BlogSettings
Price="10"
title="BLACKswastik" />
You made a new config reference so it can be its own node now.

.NET 4.0 application on network share causes SecurityException

Today I experienced a weird problem while trying to remotely debug an application built for the .NET 4.0 runtime.
The application resides on a network share and executed by a remote machine. However the application crashes each time during load because of a SecurityException raised by a permission demand in the System.Configuration.ConfigurationManager.GetSection() method. I have not checked if other permission demands in the base class library also cause a security exception but in all cases this shouldn't be happening with the new CLR.
The application is running in full trust (checked it while debugging and as usual this must be always true for intranet applications in CLR 4.0) so I am clueless how a permission demand can cause an exception in this case. When built against the 3.5 SP1 runtime (which first introduced full trust for network shared apps by default) everythings runs as expected.
I pasted the sample code below. Any help is greatly appreciated.
using System;
using System.Configuration;
namespace ConsoleApplication1
{
public sealed class AssetsSection : ConfigurationSection
{
private static readonly ConfigurationProperty s_propPath;
private static readonly ConfigurationPropertyCollection s_properties;
static AssetsSection()
{
s_propPath = new ConfigurationProperty("path", typeof(String));
s_properties = new ConfigurationPropertyCollection()
{
s_propPath
};
}
public static AssetsSection Get()
{
return (AssetsSection) ConfigurationManager.GetSection("test/assets");
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return s_properties;
}
}
public String Path
{
get
{
return (String) base[s_propPath];
}
set
{
base[s_propPath] = value;
}
}
}
class Program
{
static void Main(String[] args)
{
Console.WriteLine(AssetsSection.Get().Path);
Console.ReadLine();
}
}
}
And the App.config file;
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="test">
<section name="assets" type="ConsoleApplication1.AssetsSection, ConsoleApplication1"/>
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
</startup>
<test>
<assets path="..\Assets"/>
</test>
</configuration>
Try loading the configuration first and open your section on that:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AssetsSection configSection = (AssetsSection)config.GetSection("test/assets");
I ran into the same issue with .NET 4 and this works for me.
This is due to a known bug in .NET 4.0 when running the application from a network share.
The follow code fails with a SecurityException. Note that it only fails when you have defined a custom type for the section like in this example AssetsSection:
ConfigurationManager.GetSection("test/assets");
One fix is the solution suggestion by Timo to use a different API. Another solution is to apply the patch provided by Microsoft.
The bug and the related hotfix is filed under KB2580188.
If you add your own class to map the section like this:
[XmlRoot("Interface")]
public class MySectionClass
{
[XmlAttribute()]
public string MyAttr1
{
get;
set;
}
public string MyAttr2
{
get;
set;
}
}
You can use this code:
ConfigurationSection configSection =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).
GetSection("MySection");
XmlSerializer xs = new XmlSerializer(typeof(MySectionClass));
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(configSection.SectionInformation.GetRawXml());
XmlNodeReader xnr = new XmlNodeReader(xdoc.DocumentElement);
MySectionClass section = (MySectionClass)xs.Deserialize(xnr);
I'm speculating here, but I suspect it's your configuration file that's not trusted.
In your case, your configuration file is referencing a type ConsoleApplication1.AssetsSection that does not have a strong name that could be used as evidence.
Can you provide more details and the exact error message.

C# AppSettings: Is there a easy way to put a collection into <appSetting>

i tried
<appSettings >
<add key="List" value="1"/>
<add key="List" value="2"/>
<add key="List" value="3"/>
</appSettings >
and System.Configuration.ConfigurationManager.AppSettings.GetValues("List");
But i only get the last member .
How could i solve this easily?
I have dealt a similar issue and I did it with this code. Hope this helps in your problem.
In this case List (similar to my URLSection) will have a full configuration Section in web.config which you can get all values from this section then.
<configSections>
<section name="URLSection" type="A.WebConfigSection,A,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
</configSections>
<appSettings></appSettings>
<URLSection>
<urlCollection>
<add url="1" value="a"/>
<add url="2" value="b"/>
</urlCollection>
</URLSection>
I made three classes for this: ConfigElement, ConfigElementCollection, WebConfigSection.
ConfigElement
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace A
{
public class ConfigElement:System.Configuration.ConfigurationElement
{
[ConfigurationProperty("url",IsRequired=true) ]
public string url
{
get
{
return this["url"] as string;
}
}
[ConfigurationProperty("value", IsRequired = true)]
public string value
{
get
{
return this["value"] as string;
}
}
}
}
ConfigElementCollection
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace A
{
public class ConfigElementCollection:ConfigurationElementCollection
{
public ConfigElement this[int index]
{
get
{
return base.BaseGet(index) as ConfigElement;
}
}
protected override ConfigurationElement CreateNewElement()
{
return new ConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ConfigElement)(element)).url;
}
}
}
WebConfigSection
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace A
{
public class WebConfigSection:ConfigurationSection
{
public WebConfigSection()
{
}
[ConfigurationProperty("urlCollection")]
public ConfigElementCollection allValues
{
get
{
return this["urlCollection"] as ConfigElementCollection;
}
}
public static WebConfigSection GetConfigSection()
{
return ConfigurationSettings.GetConfig("URLSection") as WebConfigSection;
}
}
}
foreach (string str in ConfigurationManager.AppSettings.AllKeys)
{
if (str.ToUpper().IndexOf("SOMESPECIAL") > -1) //the somespecial ones you want to add in
lstList.Add(ConfigurationManager.AppSettings[str]);
}
NinjaSettings does this out of the box.
In the package manager console
Install-Package NinjaSettings
You would declare your list as
<appSettings>
<add key="List" value="50,20,10,100"/>
</appSettings>
then create an Interface with a mapping for list to any ICollection or Array
public interface IAppSettings
{
List<int> List { get; }
}
then access your settings user the NinjaSettings wrapper. Generally you would wire this up using IOC, but the basic usage is
var settings = new NinjaSettings<IAppSettings>().Settings;
int total = 0;
for (var i in settings.List)
{
total+=i;
}
You'd likely be better off putting this information in a separate XML file and having a reference to that file in AppSettings. That would give you a lot more flexibility around how you retrieved the information and consumed it.
The only thing would be that you'd want to create a separate (static?) class for reading the XML in a similar fashion to the System.Configuration.ConfigurationManager.AppSettings class.
If, on the other hand, it HAD to be in your Web.Config file, I would suggest the only way to achieve this simply would be to have a [pipe/comma/semi-colon] delimited array in one "List" setting.
Haacked provides a concise approach to configuration settings. His approach uses one class deriving from ConfigurationSection. So for his blog example your app.config or web.config xml representation will look like this:
<configuration>
<configSections>
<section name="BlogSettings" type="Fully.Qualified.TypeName.BlogSettings,
AssemblyName" />
</configSections>
<BlogSettings frontPagePostCount="10" title="You’ve Been Haacked" />
</configuration>
This is worth a read:
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx

Categories