title: Config files and retrieving in Azure-Functions
body: <p>I've been experimenting with .config files in Azure-Functions.</p>
  
  <p>If I write this function</p>
  
  <pre><code>using System;
  using System.Configuration;
  using System.Net;
  using System.Net.Http;
  using System.Threading.Tasks;
  
  using Microsoft.Azure.WebJobs;
  using Microsoft.Azure.WebJobs.Extensions.Http;
  using Microsoft.Azure.WebJobs.Host;
  
  
  namespace GranadaCoder.AzurePoc.AzureFunctionsOne
  {
      public static class AppSettingsTestOne
      {
          [FunctionName("AppSettingsTestOneFunctionName")]
          public static async Task&lt;HttpResponseMessage&gt; Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
          {
  
              try
              {
  
                  string rootDirectory = string.Empty;
                  if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HOME")))
                  {
                      /* running in azure */
                      rootDirectory = Environment.GetEnvironmentVariable("HOME") + "\\site\\wwwroot";
                  }
                  else
                  {
                      /* in visual studio, local debugging */
                      rootDirectory = ".";
                  }
                  string path = rootDirectory + @"\CustomConfigFiles\CustomAppSettings.config";
  
                  if (!System.IO.File.Exists(path))
                  {
                      throw new System.IO.FileNotFoundException(string.Format("NOT FOUND!!! ('{0}')", path));
                  }
                  else
                  {
                      log.Info(string.Format("File exists='{0}'", path));
                  }
  
                  ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = path };
                  Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
  
                  Configuration fileConfig = ConfigurationManager.OpenExeConfiguration(path); /* does NOT work */
                  string val1 = config.AppSettings.Settings["KeyOne"].Value;
                  string val2 = config.AppSettings.Settings["KeyTwo"].Value;
                  string val3 = config.AppSettings.Settings["KeyThree"].Value;
  
                  string msg = string.Join(",", val1, val2, val3);
  
                  return req.CreateResponse(HttpStatusCode.OK, msg);
              }
              catch (Exception ex)
              {
                  string errorMsg = ex.Message; //  ExceptionHelper.GenerateFullFlatMessage(ex);
                  log.Error(errorMsg);
                  return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
              }
          }
      }
  }
  </code></pre>
  
  <p>with this .config file (CustomAppSettings.config)</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;configuration&gt;
    &lt;appSettings&gt;
      &lt;add key="KeyOne" value="ValueOne" /&gt;
      &lt;add key="KeyTwo" value="ValueTwo" /&gt;
      &lt;add key="KeyThree" value="ValueThree" /&gt;
    &lt;/appSettings&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>It works as anticipated.</p>
  
  <p>If I use this function:</p>
  
  <pre><code>using System;
  using System.Collections.Specialized;
  using System.Configuration;
  using System.IO;
  using System.Linq;
  using System.Net;
  using System.Net.Http;
  using System.Threading.Tasks;
  using System.Xml;
  
  using Microsoft.Azure.WebJobs;
  using Microsoft.Azure.WebJobs.Extensions.Http;
  using Microsoft.Azure.WebJobs.Host;
  
  
  namespace GranadaCoder.AzurePoc.AzureFunctionsOne
  {
      public static class NameValuePairAppSettingsTest
      {
          [FunctionName("NameValuePairAppSettingsTestFunctionName")]
          public static async Task&lt;HttpResponseMessage&gt; Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
          {
  
              try
              {
                  string rootDirectory = string.Empty;
                  if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HOME")))
                  {
                      /* running in azure */
                      rootDirectory = Environment.GetEnvironmentVariable("HOME") + "\\site\\wwwroot";
                  }
                  else
                  {
                      /* in visual studio, local debugging */
                      rootDirectory = ".";
                  }
                  string path = rootDirectory + @"\CustomConfigFiles\NameValuePairSettings.config";
  
  
                  if (!System.IO.File.Exists(path))
                  {
                      throw new System.IO.FileNotFoundException(string.Format("NOT FOUND!!! ('{0}')", path));
                  }
                  else
                  {
                      log.Info(string.Format("file exists='{0}'", path));
                  }
  
                  ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = path };
                  Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
  
                  //NameValueCollection nvc = (NameValueCollection)config.GetSection("myLittleArea"); /* does not work */
  
                  ConfigurationSection myParamsSection = config.GetSection("myLittleArea");
                  /* see https://stackoverflow.com/questions/13825323/how-do-i-get-the-values-from-a-configsection-defined-as-namevaluesectionhandler */
                  string myParamsSectionRawXml = myParamsSection.SectionInformation.GetRawXml();
                  XmlDocument sectionXmlDoc = new XmlDocument();
                  sectionXmlDoc.Load(new StringReader(myParamsSectionRawXml));
                  NameValueSectionHandler handler = new NameValueSectionHandler();
                  NameValueCollection nvc = handler.Create(null, null, sectionXmlDoc.DocumentElement) as NameValueCollection;
  
                  var items = nvc.AllKeys.SelectMany(nvc.GetValues, (k, v) =&gt; new { key = k, value = v });
                  ////////foreach (var item in items)
                  ////////{
                  ////////    Console.WriteLine("{0} {1}", item.key, item.value);
                  ////////}
  
                  string msg = string.Join(",", items.ToList());
  
                  return req.CreateResponse(HttpStatusCode.OK, msg);
              }
              catch (Exception ex)
              {
                  string errorMsg = ex.Message; //  ExceptionHelper.GenerateFullFlatMessage(ex);
                  log.Error(errorMsg);
                  return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
              }
          }
      }
  }
  </code></pre>
  
  <p>with this .config file (NameValuePairSettings.config)</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;section name="myLittleArea" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" /&gt;
    &lt;/configSections&gt;
  
    &lt;myLittleArea&gt;
      &lt;add key="color" value="red"/&gt;
      &lt;add key="street" value="main"/&gt;
      &lt;add key="month" value="july"/&gt;
      &lt;add key="candy" value="snickers"/&gt;
    &lt;/myLittleArea&gt;
  
  &lt;/configuration&gt;
  </code></pre>
  
  <p>Everything works ok.</p>
  
  <p>(Drum Roll).</p>
  
  <p>If I create a custom configuration section.</p>
  
  <pre><code>using System.Configuration;
  
  namespace GranadaCoder.AzurePoc.ConfigurationLibrary.MyCustomConfigurationSettings
  {
      public static class MyCustomConfigurationSettingsConfigurationRetriever
      {
          public static readonly string ConfigurationSectionName = "MyCustomConfigurationSettingsConfigurationSectionName";
  
          /*
          public static MyCustomConfigurationSettingsConfigurationSection GetMyCustomConfigurationSettings()
          {
              MyCustomConfigurationSettingsConfigurationSection returnSection = (MyCustomConfigurationSettingsConfigurationSection)ConfigurationManager.GetSection(ConfigurationSectionName);
              if (returnSection != null)
              {
                  return returnSection;
              }
  
              return null;
          }
          */
  
          public static MyCustomConfigurationSettingsConfigurationSection GetMyCustomConfigurationSettings(System.Configuration.Configuration cfg)
          {
              MyCustomConfigurationSettingsConfigurationSection returnSection = (MyCustomConfigurationSettingsConfigurationSection)cfg.GetSection(ConfigurationSectionName);
              if (returnSection != null)
              {
                  return returnSection;
              }
  
              return null;
          }
      }
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>using System.Configuration;
  
  namespace GranadaCoder.AzurePoc.ConfigurationLibrary.MyCustomConfigurationSettings
  {
      public class MyCustomConfigurationSettingsConfigurationSection : ConfigurationSection
      {
          private const string FavoriteNumberPropertyName = "FavoriteNumber";
          private const string FavoriteColorPropertyName = "FavoriteColor";
  
          [ConfigurationProperty(FavoriteNumberPropertyName, IsRequired = true, DefaultValue = 100)]
          public int FavoriteNumber
          {
              get
              {
                  return (int)this[FavoriteNumberPropertyName];
              }
          }
  
          [ConfigurationProperty(FavoriteColorPropertyName, IsRequired = true, DefaultValue = ",")]
          public string FavoriteColor
          {
              get
              {
                  return (string)this[FavoriteColorPropertyName];
              }
          }
      }
  }
  </code></pre>
  
  <p>and .config (MyCustomConfigurationSettings.config)</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;section name ="MyCustomConfigurationSettingsConfigurationSectionName" type="GranadaCoder.AzurePoc.ConfigurationLibrary.MyCustomConfigurationSettings.MyCustomConfigurationSettingsConfigurationSection, GranadaCoder.AzurePoc.ConfigurationLibrary" /&gt;
    &lt;/configSections&gt;
    &lt;MyCustomConfigurationSettingsConfigurationSectionName
      FavoriteNumber="333"
      FavoriteColor="Green"
    &gt;
    &lt;/MyCustomConfigurationSettingsConfigurationSectionName&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>and azure function code</p>
  
  <pre><code>using System;
  using System.Configuration;
  using System.Net;
  using System.Net.Http;
  using System.Threading.Tasks;
  
  using Microsoft.Azure.WebJobs;
  using Microsoft.Azure.WebJobs.Extensions.Http;
  using Microsoft.Azure.WebJobs.Host;
  
  using GranadaCoder.AzurePoc.ConfigurationLibrary.MyCustomConfigurationSettings;
  
  
  
  namespace GranadaCoder.AzurePoc.AzureFunctionsOne
  {
      public static class CustomConfigurationTest
      {
          [FunctionName("CustomConfigurationTestFunctionName")]
          public static async Task&lt;HttpResponseMessage&gt; Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
          {
              try
              {
                  string rootDirectory = string.Empty;
                  if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HOME")))
                  {
                      /* running in azure */
                      rootDirectory = Environment.GetEnvironmentVariable("HOME") + "\\site\\wwwroot";
                  }
                  else
                  {
                      /* in visual studio, local debugging */
                      rootDirectory = ".";
                  }
                  string path = rootDirectory + @"\CustomConfigFiles\MyCustomConfigurationSettings.config";
  
                  log.Info(string.Format("CustomConfigurationTestFunctionName HostingEnvironment.ApplicationPhysicalPath='{0}'", System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath));
  
                  if (!System.IO.File.Exists(path))
                  {
                      throw new System.IO.FileNotFoundException(string.Format("NOT FOUND!!! ('{0}')", path));
                  }
                  else
                  {
                      log.Info(string.Format("File exists='{0}'", path));
                  }
  
                  ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = path };
                  Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
  
                  MyCustomConfigurationSettingsConfigurationSection customSection = MyCustomConfigurationSettingsConfigurationRetriever.GetMyCustomConfigurationSettings(config);
  
                  string msg = string.Join(",", customSection.FavoriteNumber.ToString(), customSection.FavoriteColor);
  
                  return req.CreateResponse(HttpStatusCode.OK, msg);
              }
              catch (Exception ex)
              {
                  string errorMsg = ex.Message; //  ExceptionHelper.GenerateFullFlatMessage(ex);
                  log.Error(errorMsg);
                  return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
              }
          }
      }
  }
  </code></pre>
  
  <p>The above does not work.</p>
  
  <p>I get an error</p>
  
  <p>"An error occurred creating the configuration section handler for MyCustomConfigurationSettingsConfigurationSectionName: Could not load file or assembly 'GranadaCoder.AzurePoc.ConfigurationLibrary' or one of its dependencies. The system cannot find the file specified. (C:\blah\blah\blah\bin\Debug\net461\CustomConfigFiles\MyCustomConfigurationSettings.config line 4)"</p>
  
  <p>The file IS THERE (see image)</p>
  
  <p>Any idea why the custom configuration does not work?</p>
  
  <p><a href="https://i.stack.imgur.com/oJxeq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oJxeq.png" alt="enter image description here"></a></p>