Rules for runtime versioning:
If version application is built with is present, that version will be used
If version application is built with is not present and nothing specified by supportedRuntime then the latest version of framework on machine is used.
To verify that shared assembly works with multiple assemblies it can be a pain installing / uninstalling the assembly from the GAC multiple times. Can alleviate by setting the environment variable DEVPTAH to point to the location of the assembly and setting the developmentMode to true:
<configuration>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
</configuration>
Can specify where to find specific version of assembly. Can use .NET Framework 2.0 configuration tool or by manually editing the machine configuration file. The codeBase element allows specification of version and location information, e.g.
<configuration>
<runtime>
<assemblyBinding ...>
<dependentAssembly>
<assemblyIdentity name="myprogram" ... />
<codeBase version="x.0.0.0" href="http://www.example.com/myprogram.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Two primary sections, connectionStrings and appSettings, support common configuration requirements, e.g.
<configuration>
<appSettings>
<add key"Foo" value "bar"/>
</appSettings>
<connectionStrings>
<add name="WorksString" providerName="System.Data.SqlClient" connectionString="Data Source=localhost" />
</connectionStrings>
</configuration>
Previously accessed appSetting entries via ConfigurationSettings, but this has been obsoleted, e.g.
string barVar = ConfigurationSettings.AppSettings["Foo"];
Correct way to access is via ConfigurationManager, e.g.
string barVar = ConfigurationManager.AppSettings["Foo"];
Can enumerate AppSettings, as follows:
NameValueCollection coll = ConfigurationManager.AppSettings;
IEnumerator enum = coll.Keys.GetEnumerator();
Connection settings are slightly more involved, but still intuitive. Previously .NET made no real distinction between connection strings and others. Now strong typing is supported allowing provider type to be supported. Access almost identically to AppSettings, primary difference instead of using NameValueCollection is use of ConnectionStringSettingsCollection as exposed by ConnectionStrings property, e.g.
ConnectionStringSettings conn = ConfigurationManager.ConnectionStrings["WorksString"];
Web applications should use the WebConfigurationManager instead of the ConfigurationManager.
Apply to application as a whole rather than a specific user, typical candidates are database connection strings, web service urls, remoting settings, etc.
Can construct by hand, but discouraged because configuration files demand extreme precision. Other options is to use Settings class and the designer. To use designer add new project item of type Settings File. The IDE presents designer allowing creation and management of settings. Generates appropriate class to provide access to the settings, e.g.
SampleSettings mySettings = new SampleSettings();
Debug.WriteLine(mySettings.WebServiceUrl);
Last mechanism is ApplicationSettingsBase - as used by Visual Studio. To use create class that derives from ApplicationSettingsBase and decorate each property with either UserScopedSettings or ApplicationScopedSettings attribute, e.g.
class AppSettingsHelper : ApplicationSettingsBase
{
[UserScopedSetting()]
public String Key
{
get { return (this["Key"] as String); }
set { this["Key"] = value; }
}
}
Provides ability to add assemblies or change their location without requiring recompilation of application. For example...
3-tier application with all layers running on same machine. By using remoting can spread out load between machines. If components have been registered in code then recompilation will be required to point to the new assembly locations. By using configuration files the assemblies can be deployed to new machines and used when the configuration file is updated - with no need to restart the application.
To register a component as a server need to specify fully qualified object name and assembly, the type (Singleton or Single Call) and Uniform Resource Identifier. If being used on IIS then the URI must have a .rem extension:
<system.runtime.remoting>
<application name="MyApplication">
<service>
<wellknown type="FullyQualifiedName,AssemblyName" mode="Singleton" objectUri="MyClass.rem"/>
</service>
</application>
</system.runtime.remoting>
For a client to consume the assembly similar entries are made, except the mode is not required and the URI points to the location where the object is being made available, e.g.
<system.runtime.remoting>
<application name="MyClientApplication">
<service>
<wellknown type="FullyQualifiedName,AssemblyName" objectUri="http://localhost:5000/MyClass.rem"/>
</service>
</application>
</system.runtime.remoting>
In some circumstances it is necessary to add custom functionality to the features provided by the Microsoft Windows Installer. These custom installers should derive from the Installer class.
Main reason for using installers:
To create and use an Installer derived class:
To start installation call the Install method. If no errors are found then Commit is called at the end of the installation.
To launch an installer programmatically use either the AssemblyInstaller or ComponentInstaller.
IDictionary actions = new Hashtable();
AssemblyInstaller customAssemblyInstaller = new AssemblyInstaller("CustomInstaller.dll", args);
customAssemblyInstaller.UseNewContext = true;
customAssemblyInstaller.Install(actions);
customAssemblyInstaller.Commit(actions);
To uninstall:
IDictionary actions = new Hashtable();
AssemblyInstaller customAssemblyInstaller = new AssemblyInstaller("CustomInstaller.dll", args);
customAssemblyInstaller.UseNewContext = true;
customAssemblyInstaller.Uninstall(actions);
customAssemblyInstaller.Commit(actions);
Access tool via Administrative Tools or the SDK command prompt. Available options
Manage assembly cache
Manage configured assemblies
Configure code access security policy
Adjust remoting services
Manage individual applications
Multiple things that can be reset in a configuration, most common being security settings. Easiest way to do this is select the "Runtime Security Policy" node and choose "Reset All Policy Levels".
ConfigurationManager = primary vehicle through which configuration settings retrieved. Using the appSettings section of the ConfigurationManager provides access to every value in the appSettings section of the configuration file.
Can use the ConnectionStrings property (as discussed earlier).
Another possibility is through the GetSection method. In the configSections portion of the configuration file specify the name of the section, e.g.
<configSections>
<sectionGroup name="MyFirstSectionGroup">
<section name="MyFirstSection" ... />
</sectionGroup>
</configSections>
Then specify the group and section, e.g.
<MyFirstSectionGroup>
<MyFirstSection>
<Value>
<Identifier>11</Identifier>
<SettingValue>System.Data.SqlClient</SettingValue>
</Value>
</MyFirstSection>
</MyFirstSectionGroup>
Can have as many section groups and sections as want. To retrieve...
ValuesHandler vals = ConfigurationManager.GetSection("MyFirstSectionGroup/MyFirstSection") as ValuesHandler;
To save call the Save or SaveAs method of the Configuration object.
System.Configuration class has multiple interfaces that can be implemented to achieve precise functionality. Some, like IConfigurationSectionHandler are for general purpose use, others like ISettingsProviderService are more specific (e.g. providing design time support components).
The IConfigurationSectionHandler provides a high degree of granularity when accessing configuration information. It has been depreciated in .Net 2.0 and use should now be made of the ConfigurationSection class.
To create a ConfigurationSection named Chapter9Section add the following declaration:
<configSections>
<section name="Chapter9Section" type="Chapter9.Configuration.ConfigHandler, App_Code" />
</configSections>
The first portion of the type section takes a fully qualified object name (namespace.objectname) a comma and then the Assembly name (in this example the assembly name is App_Code).
In this example the ConfigurationSection will be implemented with two elements, note only one ConfigurationSection will be used although multiple ones can be. When a ConfigurationSection is used it is asses to the ConfigurationSectionCollection and can be retrieved by name or index. A ConfigurationSection can be as complex as required
<Chapter9Section LastName="Ryan" FirstName="William" />
Can use ConfigurationSection as a base for class to access these values:
public class ConfigHandler : ConfigurationSection
{
[ConfigurationProperty("LastName", IsRequired=false, DefaultValue = "NotGiven")]
public string LastName
{
get { return (string) base["LastName"];}
set { base["LastName"] = value;}
}
[ConfigurationProperty("FirstName", IsRequired=false, DefaultValue = "NotGiven")]
public string FirstName
{
get { return (string) base["FirstName"];}
set { base["FirstName"] = value;}
}
}
To use
Configuration Chapter9Config = WebConfiguration.OpenWebConfiguration(Request.ApplicationPath);
Chapter9.Configuration.ConfigHandler Chapter9Section = (Chapter9.Configuration.ConfigHandler) Chapter9Config.GetSection("Chapter9Section");
Response.Write(Chapter9Section.FirstName);
// Clear config sections from config object
Chapter9Config.Sections.Clear();
// Add new section
Chapter9Config.Sections.Add("Chapter9Section", Chapter9Section);
Chapter9Config.Save();
The IApplicationSettingsProvider is useful, supporting 3 methods:
Provides support for:
This functionality is implemented by ApplicationSettingsBase and so is easily available for use (if required). In addition this class provides:
<User Name>.config
that is stored in a Windows Special Folder accessed via the Application class through Application.LocalUserAppDataPathIConfigurationSectionHandler objects provide the ability to strongly type data. The value can be checked by the object before passing on to the client. This is not just restricted to type checking but can extend to value validation (e.g. the value is a valid US telephone number).