Setting web application settings from the same web application, without hard coded file locations.

November 16, 2009

April 09

I have often wanted the ability to be able to change settings within a web application, but have not found a simple way to achieve that without having some sort of path setting somewhere.

How I currently use this, is creating a page to configure the system from. We often have to develop in staging and production environments. The biggest cause of exceptions and errors, in my humble opinion, is usually configuration. Having to use GUID’s for most of these settings it is time consuming to validate all of the GUID’s manually.

Using this approach of having a web page to configure and test all of the settings that is currently in the system, I can provide the administrators of the servers a simple and effective way to test the system, without having any specific knowledge about the application.

 

 /// <summary>
    /// Updates the configuration file, if the key that you are updating is within the appSettings section.
    /// It also refreshes the AppSetting Cache so that the applied setting, is availible in your web application.
    /// The keys needs to have been created within the config file before hand, but it could be empty.  example of an
    /// application key, that will be able to be set.
    /// <code>
    /// <add key="SupportQueueId" value=""/>
    /// </code>
    /// </summary>
    /// <param name="key">The key</param>
    /// <param name="value">The value</param>
    public static void UpdateConfigurationFile(string key, string value)
    {
        string configurationFile = getConfigurationFilePath();
        XmlDocument xmldoc = new XmlDocument();
        if (configurationFile == null)
        {
            throw new ConfigurationErrorsException(Resource.ConfigurationErrorFileNotFound);
        }

        xmldoc.Load(configurationFile);
        XmlNode node = xmldoc.DocumentElement.SelectSingleNode("//appSettings//add[@key='" + key + "']");

        if (!string.IsNullOrEmpty(node.Attributes[1].Value))
        {
            node.Attributes[1].Value = value;
            xmldoc.Save(configurationFile);
        }

        //update the cached setting
        ConfigurationManager.AppSettings.Set(key, value);
    }
    private static string getConfigurationFilePath()
    {
        string configFileLocation;
        if (HttpContext.Current.Request.PhysicalApplicationPath != null)
        {
            configFileLocation = string.Concat(HttpContext.Current.Request.PhysicalApplicationPath, Resource.ConfigurationFile);
        }
        else
        {
            throw new ConfigurationErrorsException(Resource.ConfigurationErrorHttpContextNotFound);
        }
        return configFileLocation;
    }
    /// <summary>
    /// Write exceptions to the event logs.
    /// The most useful information is within the InnerException, if CRM had a problem with the web request.  Other than that, all errors are unexpected.
    /// Examples of potential errors that might originate from CRM, is if somebody is trying to import a email, that another person has deleted just before
    /// the import is executed.
    ///
    /// </summary>
    public static void LogErrorMessage(Exception errorHandler)
    {
        if (!EventLog.SourceExists(AppDomain.CurrentDomain.FriendlyName))
        {
            EventLog.CreateEventSource(AppDomain.CurrentDomain.FriendlyName, Resource.DestinationEventLog);
        }

        EventLog myLog = new EventLog();
        myLog.Source = AppDomain.CurrentDomain.FriendlyName;
        try
        {
            myLog.WriteEntry(errorHandler.InnerException.Data.ToString(), EventLogEntryType.Error);
        }
        catch (NullReferenceException)
        {
            myLog.WriteEntry(errorHandler.Message, EventLogEntryType.Warning);
        }
    }
    /// <summary>
    /// Creates credentials based on settings in the web.config
    /// If UseIntegratedAuthentication is set to false, it use the configured Service Account Settings.  This is mainly for debugging
    /// and by not using integrated authentication, all the action's and records that the system has a effect on will be owned by the configured user.
    /// When using integrated authentication, records will be owned by user executing the function. 
    /// </summary>
    /// <returns></returns>
    private static NetworkCredential getNetworkCredential()
    {
        NetworkCredential credential;

        if (ConfigurationManager.AppSettings[Resource.AppSettingsUseIntegratedAuthentication].ToLower().Contains("true"))
        {
            credential = CredentialCache.DefaultNetworkCredentials;
        }
        else
        {
            string userName = ConfigurationManager.AppSettings[Resource.ServiceAccountUserName];
            string password = ConfigurationManager.AppSettings[Resource.ServiceAccountPassword];
            string domain = ConfigurationManager.AppSettings[Resource.ServiceAccountDomain];

            credential = new NetworkCredential(userName, password, domain);
        }
        return credential;
    }
    /// <summary>
    /// The web service proxy, had to be over ridden, in order to enable multiple calls to the web service, to not drop the connection and
    /// impacting a potential separate thread, that might be waiting for the results.  It fails with a error message
    /// </summary>
    /// <returns></returns>
    /// <seealso cref="WebServiceKeptAlive"/>
    public static CrmService CrmWebServiceProxy()
    {
        CrmService service = new WebServiceKeptAlive();
        service.Credentials = getNetworkCredential();

        return service;
    }
}

 
 

Follow

Get every new post delivered to your Inbox.