C# WCF 系统配置错误异常:未识别的元素 'ManagedService'。

3
在一个WCF应用程序中,我有一些自定义配置类可供在app.config中使用。然而,我从WCF服务主机得到了以下堆栈跟踪(它试图在WCF服务的构造函数中检索自定义配置):
System.Reflection.TargetInvocationException:目标调用的异常已被抛出。---> System.Configuration.ConfigurationErrorsException:无法识别元素“ManagedService”(Service.dll.config第8行)。在System.Configuration.BaseConfigurationRecord.EvaluateOne(String [] keys,SectionInput input,Boolean isTrusted,FactoryRecord factoryRecord,SectionRecord sectionRecord,Object parentResult)中;在System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord,SectionRecord sectionRecord,Object parentResult,Boolean getLkg,Boolean getRuntimeObject,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSection(String configKey)中;在System.Configuration.ConfigurationManager.GetSection(String sectionName)中;在ManagementService..ctor()的第42行;--- 内部异常堆栈跟踪结束 --- 在System.RuntimeMethodHandle._InvokeConstructor(IRuntimeMethodInfo method,Object [] args,SignatureStruct & signature,RuntimeType declaringType)中;在System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr,Binder binder,Object [] parameters,CultureInfo culture)
在System.ServiceModel.Description.ServiceDescription.CreateImplementation(Type serviceType)中;在System.ServiceModel.Description.ServiceDescription.GetService(Type serviceType)中;在System.ServiceModel.ServiceHost.CreateDescription(IDictionary`2 & implementedContracts)中;在System.ServiceModel.ServiceHostBase.InitializeDescription(UriSchemeKeyedCollection baseAddresses)中;在System.ServiceModel.ServiceHost..ctor(Type serviceType,Uri [] baseAddresses)中;在Microsoft.Tools.SvcHost.ServiceHostHelper.CreateServiceHost(Type type,ServiceKind kind)中;在Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)中。System.Configuration.ConfigurationErrorsException:无法识别元素“ManagedService”(Service.dll.config第8行)。在System.Configuration.BaseConfigurationRecord.EvaluateOne(String [] keys,SectionInput input,Boolean isTrusted,FactoryRecord factoryRecord,SectionRecord sectionRecord,Object parentResult)中;在System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord,SectionRecord sectionRecord,Object parentResult,Boolean getLkg,Boolean getRuntimeObject,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey,Boolean getLkg,Boolean checkPermission,Boolean getRuntimeObject,Boolean requestIsHere,Object & result,Object & resultRuntimeObject)中;在System.Configuration.BaseConfigurationRecord.GetSection(String configKey)中;在System.Configuration.ConfigurationManager.GetSection(String sectionName)中;在ManagementService..ctor()的第42行。

非常抱歉看到这个让人头疼的堆栈跟踪。

我查看了很多关于此错误的教程和其他问题,但是所有的建议或解决方案都没有任何进展。

以下是app.config的相关部分:

<configSections>
     <section name="ManagedServices" type="Service.Configuration.ManagedServicesSection, Service, Version=1.0.0.0, Culture=neutral " allowLocation="true" allowDefinition="Everywhere" restartOnExternalChanges="false" />
</configSections>
  <ManagedServices>
     <services>
        <ManagedService serviceAssembly="Service" serviceType="Service.Runnables.HostManagerRunner" identifier="HostManager" priority="0">
           <clear />
        </ManagedService>
        <ManagedService serviceAssembly="Service" serviceType="Service.Runnables.TimeoutMonitor" identifier="TimeoutMonitor" priority="0">
           <add key="timeoutLength" value="30" />
           <add key="runInterval" value="30" />
        </ManagedService>
     </services>
  </ManagedServices>

基本上,这个WCF服务用于管理在启动时动态加载和启动的其他服务(通过此配置通知)。 <ManagedServices> 来自 ManagedServicesSection,后者继承自 ConfigurationSection
public class ManagedServicesSection : ConfigurationSection
{

  [ConfigurationProperty("services", IsDefaultCollection = true)]
  public ManagedServiceCollection ServiceCollection
  {
     get { return (ManagedServiceCollection) base["services"]; }
  }

}

正如您从中所看到的,<services>是一个继承自ConfigurationElementCollectionMangedServiceCollection
public class ManagedServiceCollection : ConfigurationElementCollection
{

  public ManagedServiceCollection()
  {
  }

  public override ConfigurationElementCollectionType CollectionType
  {
     get
     {
        return ConfigurationElementCollectionType.BasicMap;
     }
  }

  public ManagedService this[int index]
  {
     get { return BaseGet(index) as ManagedService; }
     set
     {
        if (BaseGet(index) != null)
           BaseRemoveAt(index);

        BaseAdd(index, value);
     }
  }

  public ManagedService this[string name]
  {
     get { return BaseGet(name) as ManagedService; }
     set 
     { 
        if (BaseGet(name) != null)
           BaseRemove(name);

        BaseAdd(value);
     }
  }

  protected override ConfigurationElement CreateNewElement()
  {
     return new ManagedService();
  }

  protected override object GetElementKey(ConfigurationElement element)
  {
     return ((ManagedService)element).Identifier;
  }
}

这个集合包含从 ConfigurationElement 继承的 ManagedService
public class ManagedService : ConfigurationElement
{
  [ConfigurationProperty("serviceAssembly", IsRequired = true)]
  public string ServiceAssembly
  {
     get { return (string) this["serviceAssembly"]; }
     set { this["serviceAssembly"] = value; }
  }

  [ConfigurationProperty("serviceType", DefaultValue = "IRunnable", IsRequired = true)]
  public string ServiceType 
  { 
     get { return (string) this["serviceType"]; }
     set { this["serviceType"] = value; }
  }

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


  [ConfigurationProperty("priority", DefaultValue = 0, IsRequired = false)]
  public int Priority
  {
     get { return (int) this["priority"]; }
     set { this["priority"] = value; }
  }

  [ConfigurationProperty("serviceParameters", IsDefaultCollection = true)]
  public ServiceParameterCollection ServiceParameters
  {
     get { return (ServiceParameterCollection)base["serviceParamters"]; }
  }
}

这段代码可以在pastiepastie.org/private/jkiylqsrklpcdbtfdrajq上更容易地查看。

1个回答

1

我无法编译您的示例,因为缺少ServiceParameterCollection...所以我已经为您准备了我的工作示例。我们开始吧...

首先让我们创建配置类,注意AddItemName ConfigurationCollection参数(我认为这是您代码中缺少的部分):

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

namespace GP.Solutions.WF.DocumentProvider.Entities.SharePoint
{
    /// <summary>
    /// Base SharePoint 2010 provider contiguration
    /// </summary>
    [Serializable]
    public class SharePoint2010Settings : ConfigurationSection
    {
        /// <summary>
        /// DocumentStorageRoot
        /// </summary>
        [ConfigurationProperty("SiteUrl", IsRequired = true, DefaultValue = "")]
        public string SiteUrl
        {
            get { return (string)base["SiteUrl"]; }
            set { base["SiteUrl"] = value; }
        }

        /// <summary>
        /// TitleProperty
        /// </summary>
        [ConfigurationProperty("TitleProperty", IsRequired = true, DefaultValue = "Title")]
        public string TitleProperty
        {
            get { return (string)base["TitleProperty"]; }
            set { base["TitleProperty"] = value; }
        }

        /// <summary>
        /// ProvideFileAsLink
        /// </summary>
        [ConfigurationProperty("ProvideFileAsLink", IsRequired = true, DefaultValue = true)]
        public bool ProvideFileAsLink
        {
            get { return (bool)base["ProvideFileAsLink"]; }
            set { base["ProvideFileAsLink"] = value; }
        }

        /// <summary>
        /// DocumentCategories
        /// </summary>
        [ConfigurationProperty("DocumentCategories")]
        public SharePointDocumentCategoryCollection DocumentCategories
        {
            get { return (SharePointDocumentCategoryCollection)base["DocumentCategories"]; }
            set { base["DocumentCategories"] = value; }
        }

    }

    /// <summary>
    /// Configuration element that holds SharePointDocumentCategory collection
    /// </summary>
    [ConfigurationCollection(typeof(SharePointDocumentCategory), AddItemName = "DocumentCategory", CollectionType = ConfigurationElementCollectionType.BasicMap)]
    public class SharePointDocumentCategoryCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new SharePointDocumentCategory();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((SharePointDocumentCategory)element).CategoryName;
        }
    }

    /// <summary>
    /// Configuration element that holds information for specific document category
    /// </summary>
    [Serializable]
    public class SharePointDocumentCategory: ConfigurationElement
    {
        /// <summary>
        /// CategoryName
        /// </summary>
        [ConfigurationProperty("CategoryName", IsRequired = true, DefaultValue = "")]
        public string CategoryName
        {
            get { return (string)base["CategoryName"]; }
            set { base["CategoryName"] = value; }
        }

        /// <summary>
        /// FolderName
        /// </summary>
        [ConfigurationProperty("FolderName", IsRequired = true, DefaultValue = "")]
        public string FolderName
        {
            get { return (string)base["FolderName"]; }
            set { base["FolderName"] = value; }
        }


        /// <summary>
        /// TitleProperty
        /// </summary>
        [ConfigurationProperty("OverwriteFiles", IsRequired = true, DefaultValue = true)]
        public bool OverwriteFiles
        {
            get { return (bool)base["OverwriteFiles"]; }
            set { base["OverwriteFiles"] = value; }
        }

        /// <summary>
        /// DocumentCategories
        /// </summary>
        [ConfigurationProperty("CategoryFields")]
        public SharePointCategoryFieldsCollection CategoryFields
        {
            get { return (SharePointCategoryFieldsCollection)base["CategoryFields"]; }
            set { base["CategoryFields"] = value; }
        }

    }

    /// <summary>
    /// Configuration element that holds SharePointDocumentCategory collection
    /// </summary>
    [ConfigurationCollection(typeof(SharePointDocumentCategory), AddItemName = "CategoryField", CollectionType = ConfigurationElementCollectionType.BasicMap)]
    public class SharePointCategoryFieldsCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new SharePointCategoryField();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((SharePointCategoryField)element).FieldName;
        }
    }

    /// <summary>
    /// Class that determines specific field
    /// </summary>
    [Serializable]
    public class SharePointCategoryField : ConfigurationElement
    {
        /// <summary>
        /// FolderName
        /// </summary>
        [ConfigurationProperty("FieldName", IsRequired = true, DefaultValue = "")]
        public string FieldName
        {
            get { return (string)base["FieldName"]; }
            set { base["FieldName"] = value; }
        }
    }

}

这里是web.config的部分:

  <configSections>
    <sectionGroup name="CustomConfiguration">
      <section name="SharePoint2010Section" type="GP.Solutions.WF.DocumentProvider.Entities.SharePoint.SharePoint2010Settings,CustomConfiguration" allowDefinition="Everywhere" allowLocation="true"/>
    </sectionGroup>

  </configSections>

  <CustomConfiguration>

    <SharePoint2010Section SiteUrl="http://server" TitleProperty="Title" ProvideFileAsLink="false">
        <DocumentCategories>

          <DocumentCategory CategoryName="Vhodni računi" FolderName="" OverwriteFiles="true">
            <CategoryFields>
              <CategoryField FieldName="Datum" />
              <CategoryField FieldName="Vrednost" />
            </CategoryFields>
          </DocumentCategory>

          <DocumentCategory CategoryName="Zahtevek za dopust" FolderName="" OverwriteFiles="true">
            <CategoryFields>
              <CategoryField FieldName="Datum od" />
              <CategoryField FieldName="Datum do" />
            </CategoryFields>
          </DocumentCategory>

        </DocumentCategories>
    </SharePoint2010Section>
  </CustomConfiguration>

有趣的是,我在 MSDN 文档 http://msdn.microsoft.com/en-us/library/2tw134k3.aspx 中看到了这个,并尝试了一下。MSDN 页面说,在部分组中嵌套部分元素是可选的 - The.Anti.9
另外,当我尝试时,出现了不同的错误。然后它说“配置中没有ManagedServices部分”。 - The.Anti.9
好的,那我们继续前进。 - Gregor Primar
我觉得我能看出问题所在...您正在使用集合,但缺少额外的属性。 - Gregor Primar
示例已发布。请注意我在类上放置的属性。这将为您完成工作。 - Gregor Primar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接