I am trying to get value of service in my application from app.config. I have to send it to the application which shows the URL. A web service which I am consuming in this aplication also using it so can not move it to appSettings.
I want to get this value 'http://192.168.4.22:82/Service.asmx' through c# code.
<applicationSettings>
<SDHSServer.Properties.Settings>
<setting name="DOServer_WebReference1_Service" serializeAs="String">
<value>http://192.168.4.22:82/Service.asmx</value>
</setting>
</SDHSServer.Properties.Settings>
</applicationSettings>
Not sure i get the question,
string s = SDHSServer.Properties.Settings.DOServer_WebReference1_Service;
will get you it
If I understand you correctly you have two Visual Studio C# projects. The first (project A) has a setting you want to access in the second (project B). To do that you have to perform the following steps:
Add a reference from project B to project A
Change the access modifier of the settings i project A to public (default is internal)
Now you can access the setting in project B, in your case using the fully qualified name SDHSServer.Properties.Settings.Default.DOServer_WebReference1_Service
Note that in the settings editor you can set a value for the setting. This is the default value for the setting and this value is also stored in the App.config file for the project. However, you can override this value by providing another value in the App.config file for the application executing.
In this example, the App.config file for project A will contain the value for the setting which is http://192.168.4.22:82/Service.asmx. However, you can override this in the App.config file for project B to get another value. That is probably not what you want to do but you should be aware of this.
I use this code in a ASP.Net 4.0 site to pull section data out of the 'applicationsetting' section:
public sealed class SiteSupport {
/// <summary>
/// Retrieve specific section value from the web.config
/// </summary>
/// <param name="configSection">Main Web.config section</param>
/// <param name="subSection">Child Section{One layer down}</param>
/// <param name="innersection">Keyed on Section Name</param>
/// <param name="propertyName">Element property name</param>
/// <returns></returns>
/// <example>string setting = NoordWorld.Common.Utilities.SiteSupport.RetrieveApplicationSetting("applicationSettings", "NoordWorld.ServiceSite.Properties.Settings", "ServiceWS_SrvWebReference_Service", "value")</example>
public static string RetrieveApplicationSetting(string configSection, string subSection, string innersection, string propertyName) {
string result = string.Empty;
HttpWorkerRequest fakeWorkerRequest = null;
try {
using (TextWriter textWriter = new StringWriter()) {
fakeWorkerRequest = new SimpleWorkerRequest("default.aspx", "", textWriter);
var fakeHTTPContext = new HttpContext(fakeWorkerRequest);
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = fakeHTTPContext.Server.MapPath(#"~/Web.config") }, ConfigurationUserLevel.None);
ConfigurationSectionGroup group = config.SectionGroups[configSection];
if (group != null) {
ClientSettingsSection clientSection = group.Sections[subSection] as ClientSettingsSection;
if (clientSection != null) {
SettingElement settingElement = clientSection.Settings.Get(innersection);
if (settingElement != null) {
result = (((SettingValueElement)(settingElement.ElementInformation.Properties[propertyName].Value)).ValueXml).InnerText;
}
}
}
}
} catch (Exception ex) {
throw ex;
} finally {
fakeWorkerRequest.CloseConnection();
}
return result;
}
}
https://www.ServiceWS.com/webservices/Golf
Depends something like this.
var s = SDHSServer.Properties.Settings.Default.DOServer_WebReference1_Service;
or
var s = SDHSServer.Properties.Settings.DOServer_WebReference1_Service;
Related
I have a .net core app using entity framework core. When running entity framework migrations or updates via the command line, I get a "value cannot be null. Parameter name: connectionString"
The connection string is kept as an environment variable:
ConnectionStrings__SomeContextConnection ...(localdb)\\MSSQLLocalDB...
However, when I move that exact same connection string into a .json config file:
"ConnectionStrings": {
"SomeContextConnection": "...(localdb)\\MSSQLLocalDB..."
}
Then the entity framework tools recognize the connection string without issue.
When debugging the code, in Startup.cs:
var connectionString = _config.GetConnectionString("SomeContextConnection");
the connectionString variable is set to the correct string when the string is stored in either of the two locations, but it crashes when trying to connect to the database when using the environment var.
(note: in the environment variable case, the connection string is escaped so goes from
(localdb)\\MSSQLLocalDB...
to
(localdb)\\\\MSSQLLocalDB...
but the issue persists even after removing the extra back-slashes)
UPDATE:
When the connection string is moved into a Windows level environment variable, it works fine. Seems to only be an issue when using Visual Studio environment variables.
It works if you remove the double backslash after (localdb) so that there's only one backslash.
So once you've corrected that in the environment variable it should look something like this:
Server=(localdb)\MSSQLLocalDB...
I suggest you use a DesignTimeContextFactory class for the migrations:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyContext>
{
AmpContext IDesignTimeDbContextFactory<MyContext>.CreateDbContext(string[] args)
{
var connectionString = ConfigHelper.GetConnectionString();
var optionsBuilder = new DbContextOptionsBuilder<MyContext>();
optionsBuilder.UseSqlServer(connectionString);
return new AmpContext(optionsBuilder.Options);
}
}
the GetConnectionstring for me is like this and I use it throughout my application (that is for my Web API project and for integration tests):
public class ConfigHelper
{
/// <summary>
/// Gets the connectionstring from the appsettings.databasestring.json file in the solution root if there is no environment variable to be found
/// </summary>
/// <param name="solutionBasePath">Optional to not auto resolve the solution base path</param>
/// <returns></returns>
public static string GetConnectionString(string solutionBasePath = null)
{
//how to set it on IIS on the server: https://stackoverflow.com/a/36836533/1343595
var environmentString = Environment.GetEnvironmentVariable("CUSTOMCONNSTR_MyContextDb");
if (!string.IsNullOrEmpty(environmentString))
return environmentString;
if(!string.IsNullOrEmpty(solutionBasePath))
return GetStringFromConfig(Path.Combine(solutionBasePath, "appsettings.databasestring.json"));
var filePath = Path.Combine(GetSolutionBasePath(), "appsettings.databasestring.json");
return GetStringFromConfig(filePath);
}
private static string GetStringFromConfig(string filePath)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddJsonFile(filePath) //you can change the value of the connectionstring in the appsettings file and add it to gitignore so the change will not effect others
.Build();
var connectionString = config.GetConnectionString("MyContextDb");
return connectionString;
}
/// <summary>
/// Gets the current soution base path
/// </summary>
/// <returns></returns>
public static string GetSolutionBasePath()
{
var appPath = PlatformServices.Default.Application.ApplicationBasePath;
var binPosition = appPath.IndexOf("\\bin", StringComparison.Ordinal);
var basePath = appPath.Remove(binPosition);
var backslashPosition = basePath.LastIndexOf("\\", StringComparison.Ordinal);
basePath = basePath.Remove(backslashPosition);
return basePath;
}
}
Giving this one more try
I have an Enums.cs file where I have the following code
public enum AuthorizingLevels
{
[Display(Name = "AuthorizingLevels_SysSupport", ResourceType = typeof(Resources.Enums))]
SysSupport
}
And when I try calling it to display the Name, it doesn't work
ViewBag.AuthGroupFullName = Enums.AuthorizingLevels.SysSupport.ToString();
It just displays the SysSupport instead of the full name Systems Support
I went to a link provided in my previous question (How to get the Display Name Attribute of an Enum member via MVC razor code?) and added the code by Peter Kerr
/// <summary>
/// A generic extension method that aids in reflecting
/// and retrieving any attribute that is applied to an `Enum`.
/// </summary>
public static string GetDisplayName(this Enum enumValue)
{
var displayAttrib = enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
var name = displayAttrib.Name;
var resource = displayAttrib.ResourceType;
return String.IsNullOrEmpty(name) ? enumValue.ToString()
: resource == null ? name
: new ResourceManager(resource).GetString(name);
}
However, I get an error on the line
: new ResourceManager(resource).GetString(name);
An exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.dll but was not handled in user code
Additional information: Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "Resources.Enums.resources" was correctly embedded or linked into assembly "FWS" at compile time, or that all the satellite assemblies required are loadable and fully signed.
The resource file is the right one minus the .resources at the end... not sure if that should be there or not.
What am I doing wrong? I'm learning MVC and c# as I go so any help would be greatly appreciated.
Thank you
Try this. It is fairly hacky but it should hopefully give you what you need. I use Assembly.GetExecutingAssembly().GetManifestResourceNames() to get the names of all the resources in the executing assembly and then I attempt to match the file up correctly using some linq. If it finds a file that looks ok, a new ResourceManager is created as you were using in your original code.
/// <summary>
/// A generic extension method that aids in reflecting
/// and retrieving any attribute that is applied to an `Enum`.
/// </summary>
public static string GetDisplayName(this Enum enumValue)
{
var displayAttrib = enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
var name = displayAttrib.Name;
if (String.IsNullOrEmpty(name))
{
return enumValue.ToString();
}
else
{
var resource = displayAttrib.ResourceType;
if (resource != null)
{
var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames()
.Where(x => x.EndsWith(String.Format("{0}.resources", resource.Name)))
.Select(x => x.Replace(".resources", string.Empty)).ToList();
if (resources.Any())
{
return new ResourceManager(resources.First(), Assembly.GetExecutingAssembly()).GetString(name);
}
}
return name;
}
}
Is there any way to load settings from a different file other than the default App.config file at runtime? I'd like to do this after the default config file is loaded.
I use the Settings.Settings GUI in Visual Studio to create my App.config file for me. The config file ends up looking like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="SnipetTester.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<SnipetTester.Properties.Settings>
<setting name="SettingSomething" serializeAs="String">
<value>1234</value>
</setting>
</SnipetTester.Properties.Settings>
</applicationSettings>
</configuration>
In code, I'm able to access the settings like this:
Console.WriteLine("Default setting value: " + Properties.Settings.Default.SettingSomething);
The idea is that when the application is run, I should be able to specify a config file at run time and have the application load the config file into the Properties.Settings.Default object instead of using the default app.config file. The formats of the config files would be the same, but the values of the settings would be different.
I know of a way to do this with the ConfigurationManager.OpenExeConfiguration(configFile);. However, in the tests that I've run, it doesn't update the Properties.Settings.Default object to reflect the new values from the config file.
After thinking about this a bit longer, I've been able to come up with a solution that I like a little better. I'm sure it has some pitfalls, but I think it'll work for what I need it to do.
Essentially, the Properties.Settings class is automatically generated by Visual Studio; it generates the code for the class for you. I was able to find where the code was generated and add a few function calls to load a config file on its own. Here's my addition:
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
//Parses a config file and loads its settings
public void Load(string filename)
{
System.Xml.Linq.XElement xml = null;
try
{
string text = System.IO.File.ReadAllText(filename);
xml = System.Xml.Linq.XElement.Parse(text);
}
catch
{
//Pokemon catch statement (gotta catch 'em all)
//If some exception occurs while loading the file,
//assume either the file was unable to be read or
//the config file is not in the right format.
//The xml variable will be null and none of the
//settings will be loaded.
}
if(xml != null)
{
foreach(System.Xml.Linq.XElement currentElement in xml.Elements())
{
switch (currentElement.Name.LocalName)
{
case "userSettings":
case "applicationSettings":
foreach (System.Xml.Linq.XElement settingNamespace in currentElement.Elements())
{
if (settingNamespace.Name.LocalName == "SnipetTester.Properties.Settings")
{
foreach (System.Xml.Linq.XElement setting in settingNamespace.Elements())
{
LoadSetting(setting);
}
}
}
break;
default:
break;
}
}
}
}
//Loads a setting based on it's xml representation in the config file
private void LoadSetting(System.Xml.Linq.XElement setting)
{
string name = null, type = null, value = null;
if (setting.Name.LocalName == "setting")
{
System.Xml.Linq.XAttribute xName = setting.Attribute("name");
if (xName != null)
{
name = xName.Value;
}
System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs");
if (xSerialize != null)
{
type = xSerialize.Value;
}
System.Xml.Linq.XElement xValue = setting.Element("value");
if (xValue != null)
{
value = xValue.Value;
}
}
if (string.IsNullOrEmpty(name) == false &&
string.IsNullOrEmpty(type) == false &&
string.IsNullOrEmpty(value) == false)
{
switch (name)
{
//One of the pitfalls is that everytime you add a new
//setting to the config file, you will need to add another
//case to the switch statement.
case "SettingSomething":
this[name] = value;
break;
default:
break;
}
}
}
}
The code I added exposes an Properties.Settings.Load(string filename) function. The function accepts a config filename as a parameter. It will parse the file and load up any settings it encounters in the config file. To revert back to the original configuration, simply call Properties.Settings.Reload().
Hope this might help someone else!
Look at using ExeConfigurationFileMap and ConfigurationManager.OpenMappedExeConfiguration.
See Cracking the Mysteries of .Net 2.0 Configuration
The ExeConfigurationFileMap allows you to specifically configure the
exact pathnames to machine, exe, roaming and local configuration
files, all together, or piecemeal, when calling
OpenMappedExeConfiguration(). You are not required to specify all
files, but all files will be identified and merged when the
Configuration object is created. When using
OpenMappedExeConfiguration, it is important to understand that all
levels of configuration up through the level you request will always
be merged. If you specify a custom exe and local configuration file,
but do not specify a machine and roaming file, the default machine and
roaming files will be found and merged with the specified exe and user
files. This can have unexpected consequences if the specified files
have not been kept properly in sync with default files.
It depends on the type of the application:
Web Application & Windows Application - use the configSource xml attribute if you are willing to store the config files in the same folder (or subfolders) as the application
Create a settings provider and also implement IApplicationSettingsProvider. Samples here and here. You might also need to use the IConfigurationManagerInternal interface to replace the default .NET configuration manager. When implementing the provider don't forget to make a difference between user settings and application settings and the roaming profiles.
If you want to get started quickly just decompile the LocalFileSettingsProvider class (the default settings provider) and change it to your needs (you might find some useles code and might need to replicate all of the classes on which it depends).
Good luck
You can include the types so you don't need to manually update the source every time.
`private void LoadSetting(System.Xml.Linq.XElement setting)
{
string name = null, type = null;
string value = null;
if (setting.Name.LocalName == "setting")
{
System.Xml.Linq.XAttribute xName = setting.Attribute("name");
if (xName != null)
{
name = xName.Value;
}
System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs");
if (xSerialize != null)
{
type = xSerialize.Value;
}
System.Xml.Linq.XElement xValue = setting.Element("value");
if (xValue != null)
{
if (this[name].GetType() == typeof(System.Collections.Specialized.StringCollection))
{
foreach (string s in xValue.Element("ArrayOfString").Elements())
{
if (!((System.Collections.Specialized.StringCollection)this[name]).Contains(s))
((System.Collections.Specialized.StringCollection)this[name]).Add(s);
}
}
else
{
value = xValue.Value;
}
if (this[name].GetType() == typeof(int))
{
this[name] = int.Parse(value);
}
else if (this[name].GetType() == typeof(bool))
{
this[name] = bool.Parse(value);
}
else
{
this[name] = value;
}
}
}`
I have application 1 and application 2. App2 needs to verify that App1 is installed, and if it is it needs to access a property from the App1 Settings.
What would be the best way to go about this?
UPDATE
First, my apologies for never accepting an answer to this, I know it's over a year old now, but I got sidetracked immediately after asking this and then the project was changed, blah blah blah. Mea culpa...
I'm back on it now and I still need to solve this problem, but now the applications are deployed via ClickOnce, so I don't actually know where they are located. Any suggestions would be appreciated. I promise I'll select an answer this time.
The docs for ConfigurationManager.OpenExeConfiguration have an example of reading the .config file of another exe and accessing the AppSettings. Here it is:
// Get the application path.
string exePath = System.IO.Path.Combine(
Environment.CurrentDirectory, "ConfigurationManager.exe");
// Get the configuration file.
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(exePath);
// Get the AppSetins section.
AppSettingsSection appSettingSection = config.AppSettings;
As far as checking that App1 is installed, you could write a value in the Registry during installation and check it in App2 (and remove the value during uninstall).
This is a pain, I can tell you that much. I've found that the best way to do this is that you serialize the Settingsclass and use XML(code below). But try this page first:
http://cf-bill.blogspot.com/2007/10/visual-studio-sharing-one-file-between.html
public class Settings
{
public static string ConfigFile{get{return "Config.XML";}}
public string Property1 { get; set; }
/// <summary>
/// Saves the settings to the Xml-file
/// </summary>
public void Save()
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
using (TextWriter reader = new StreamWriter(ConfigFile))
{
serializer.Serialize(reader, this);
}
}
/// <summary>
/// Reloads the settings from the Xml-file
/// </summary>
/// <returns>Settings loaded from file</returns>
public static Settings Load()
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
using (TextReader reader = new StreamReader(ConfigFile))
{
return serializer.Deserialize(reader) as Settings;
}
}
}
I am storing a PNG as an embedded resource in an assembly. From within the same assembly I have some code like this:
Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");
The file, named "file.png" is stored in the "Resources" folder (within Visual Studio), and is marked as an embedded resource.
The code fails with an exception saying:
Resource MyNamespace.Resources.file.png cannot be found in class MyNamespace.MyClass
I have identical code (in a different assembly, loading a different resource) which works. So I know the technique is sound. My problem is I end up spending a lot of time trying to figure out what the correct path is. If I could simply query (eg. in the debugger) the assembly to find the correct path, that would save me a load of headaches.
This will get you a string array of all the resources:
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
I find myself forgetting how to do this every time as well so I just wrap the two one-liners that I need in a little class:
public class Utility
{
/// <summary>
/// Takes the full name of a resource and loads it in to a stream.
/// </summary>
/// <param name="resourceName">Assuming an embedded resource is a file
/// called info.png and is located in a folder called Resources, it
/// will be compiled in to the assembly with this fully qualified
/// name: Full.Assembly.Name.Resources.info.png. That is the string
/// that you should pass to this method.</param>
/// <returns></returns>
public static Stream GetEmbeddedResourceStream(string resourceName)
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
}
/// <summary>
/// Get the list of all emdedded resources in the assembly.
/// </summary>
/// <returns>An array of fully qualified resource names</returns>
public static string[] GetEmbeddedResourceNames()
{
return Assembly.GetExecutingAssembly().GetManifestResourceNames();
}
}
I'm guessing that your class is in a different namespace. The canonical way to solve this would be to use the resources class and a strongly typed resource:
ProjectNamespace.Properties.Resources.file
Use the IDE's resource manager to add resources.
I use the following method to grab embedded resources:
protected static Stream GetResourceStream(string resourcePath)
{
Assembly assembly = Assembly.GetExecutingAssembly();
List<string> resourceNames = new List<string>(assembly.GetManifestResourceNames());
resourcePath = resourcePath.Replace(#"/", ".");
resourcePath = resourceNames.FirstOrDefault(r => r.Contains(resourcePath));
if (resourcePath == null)
throw new FileNotFoundException("Resource not found");
return assembly.GetManifestResourceStream(resourcePath);
}
I then call this with the path in the project:
GetResourceStream(#"DirectoryPathInLibrary/Filename");
The name of the resource is the name space plus the "pseudo" name space of the path to the file. The "pseudo" name space is made by the sub folder structure using \ (backslashes) instead of . (dots).
public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
String pseduoName = filePath.Replace('\\', '.');
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}
The following call:
GetResourceFileStream("my.namespace", "resources\\xml\\my.xml")
will return the stream of my.xml located in the folder-structure resources\xml in the name space: my.namespace.