ConfigurationErrorsException «Неверное значение ключа», что я делаю не так? - PullRequest
3 голосов
/ 07 декабря 2010

У меня есть простое консольное приложение, которое предназначено для чтения пользовательского исключения конфигурации (код ниже), когда я запускаю его, я получаю исключение ConfigurationErrorsException с сообщением «Неверное значение ключа» при вызове ConfigurationManager.GetSection.Кто-нибудь может увидеть, что я сделал неправильно?

Файл конфигурации

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="MySection" type="ConsoleApplication1.MySection, ConsoleApplication1" />
  </configSections>
  <MySection>
    <add name="MyName" value="MyValue" />
  </MySection>
</configuration>

Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Configuration;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MySection section = (MySection)ConfigurationManager.GetSection("MySection");

            Console.WriteLine("Done");
        }
    }

    public class MySection : ConfigurationSection
    {
        [ConfigurationProperty("", IsDefaultCollection = true)]
        public MyCollection Collection
        {
            get
            {
                return (MyCollection)this[""];
            }
        }
    }

    public class MyCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new MyElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MyElement)element).Name;
        }
    }

    public class MyElement : ConfigurationElement
    {
        [ConfigurationProperty("name")]
        public string Name { get; set; }

        [ConfigurationProperty("value")]
        public string Value { get; set; }


    }
}

Исключение

System.Configuration.ConfigurationErrorsException was unhandled
  Message=Invalid key value. (C:\Users\martin.brown\documents\visual studio 2010\Projects\ConsoleApplication1\bin\Debug\ConsoleApplication1.vshost.exe.config line 7)
  Source=System.Configuration
  BareMessage=Invalid key value.
  Filename=C:\Users\martin.brown\documents\visual studio 2010\Projects\ConsoleApplication1\bin\Debug\ConsoleApplication1.vshost.exe.config
  Line=7
  StackTrace:
       at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)
       at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
       at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
       at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
       at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
       at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
       at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
       at System.Configuration.ConfigurationManager.GetSection(String sectionName)
       at ConsoleApplication1.Program.Main(String[] args) in C:\Users\martin.brown\documents\visual studio 2010\Projects\ConsoleApplication1\Program.cs:line 14
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Ответы [ 4 ]

4 голосов
/ 08 декабря 2010

Я не видел, чтобы пользовательские разделы определялись так, как вы пытаетесь это сделать.Однако вы можете заставить его работать, внеся несколько незначительных изменений

Измените конфигурацию с:

...
<MySection>
    <add name="MyName" value="MyValue" />
</MySection>
...

на:

...
<MySection>
    <MyElements>
        <add name="MyName" value="MyValue" />
    </MyElements>
</MySection>
...

, а затем слегка измените код:

public class MySection : ConfigurationSection
{
    [ConfigurationProperty("MyElements", IsDefaultCollection = true)]
    public MyCollection Collection{get {return (MyCollection) this["MyElements"];}}
}

public class MyElement : ConfigurationElement
{
    [ConfigurationProperty("name")]
    public string Name
    {
        get {return (string) (base["name"]);}
        set {base["name"] = value;}
    }

    [ConfigurationProperty("value")]
    public string Value
    {
        get {return (string) (base["value"]);}
        set {base["value"] = value;}
    }
}

(класс MyCollection остается неизменным)

Это будет работать, а также позволит вам добавить несколько значений в вашу конфигурацию:

...
<MySection>
    <MyElements>
        <add name="MyName1" value="MyValu1e" />
        <add name="MyName2" value="MyValue2" />
    </MyElements>
</MySection>
...
1 голос
/ 20 марта 2014

Если это кому-нибудь поможет, у меня была такая же ошибка, но по другой причине.В моем пользовательском классе ConfigurationElementCollection метод GetElementKey () возвращал значение, которое иногда было нулевым:

protected override Object GetElementKey(ConfigurationElement element)
{
  return ((EmulatorPositionElement)element).Method;
}

Более конкретно, он получал значение перечисления, допускающее обнуляемое значение, из пользовательского объекта ConfigurationElement:

[ConfigurationProperty("method", IsRequired = true)]
public string MethodString
{
  get { return (string)this["method"]; }
  set { this["method"] = value; }
}

public Method? Method
{
  get { return (MethodString.Trim() == "*") ? null : (Method?)Enum.Parse(typeof(Method), MethodString.Trim(), true); }
  set { MethodString = (value == null) ? "*" : value.ToString(); }
}

Я получал бы эту ошибку всякий раз, когда в файле конфигурации присутствовали дочерние элементы, где значение ConfigurationProperty было нулевым.

<position method="*" ...
0 голосов
/ 07 декабря 2010

Вы должны добавить значение ключа MyName

<add name="MyName" value="your value" /> 
0 голосов
/ 07 декабря 2010
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Configuration;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
              var section = (MySection)ConfigurationManager.GetSection("MySection");

            Console.WriteLine("Done");
        }
    }

    public class MySection : ConfigurationSection
    {
        [ConfigurationProperty("name", IsKey = true, DefaultValue = "", IsRequired = true)]
        public string Name
        {
            get { return (string)this["name"]; }
            set { this["name"] = value; }
        }

        [ConfigurationProperty("value")]
        public string Value
        {
            get { return (string)this["value"]; }
            set { this["value"] = value; }
        }

    }

    public class MyCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new MyElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MyElement)element).Name;
        }
    }

    public class MyElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsKey = true, DefaultValue = "", IsRequired = true)]
        public string Name
        {
            get { return (string)this["name"]; }
            set { this["name"] = value; }
        }

        [ConfigurationProperty("value")]
        public string Value
        {
            get { return (string)this["value"]; }
            set { this["value"] = value; }
        }


    }
}
...