3

我正在尝试在配置文件中使用实体定义来简化开发、QA、UAT 和生产版本之间的差异。这是我的配置文件开头的示例:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration [
    <!ENTITY MyStorageLocation "\\MyServer\MyStorageFolder">
    <!ENTITY MyDatabaseServer "devdb01">
]>
<configuration>
    <configSections>
    <section name="MyCustomSection" type="MyCustomSectionHandler,MyAssembly"/>
        ...
    </configSections>
<connectionStrings>
    <add name="MyConnectionString" providerName="System.Data.SqlClient" connectionString="Server=&MyDatabaseServer;;Database=MyDatabase;"/>
</connectionStrings>
    ...
<MyCustomSection>&MyStorageLocation;</MyCustomSection>
</configuration>

这似乎工作正常,为什么不是因为它是完全有效的 XML,只要我不在最终调用 ConfigurationManager.GetSection() 的自定义配置部分中使用任何这些实体。在连接字符串中使用“MyDatabaseServer”实体不会导致任何问题。在提供的示例中,只要我不在 MyCustomSection 元素中使用“MyStorageLocation”实体,一切都会正常工作,然后我只在调用 ConfigurationManager.GetSection() 请求自定义部分时遇到错误。

我最好的猜测是 ConfigurationManager 类正在获取元素的原始源并尝试将其加载为 XML,忽略整个 XML 文件的声明实体。有没有更好的方法来做到这一点,而不是重新编码自定义配置部分以支持对设置的引用而不是许多绝对设置?

我收到的错误是:

2009-01-27 14:00:53,474 [11936] ERROR MyCustomWindowsService [(null)] - Errors starting service -- shutting down
System.Configuration.ConfigurationErrorsException: Reference to undeclared entity 'MyStorageLocation'. Line 183, position 19. (D:\...\MyCustomWindowsService.exe.config line 183) ---> System.Xml.XmlException: Reference to undeclared entity 'MyStorageLocation'. Line 183, position 19.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.HandleGeneralEntityReference(String name, Boolean isInAttributeValue, Boolean pushFakeEntityIfNullResolver, Int32 entityStartLinePos)
   at System.Xml.XmlTextReaderImpl.ResolveEntity()
   at System.Xml.XmlTextReader.ResolveEntity()
   at System.Xml.XmlLoader.LoadEntityReferenceNode(Boolean direct)
   at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
   at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at System.Configuration.ErrorInfoXmlDocument.LoadFromConfigXmlReader(ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionImpl(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.CreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.BaseConfigurationRecord.CallCreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader, String filename, Int32 line)
   --- End of inner exception stack trace ---
   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, Boolean getLkg, Boolean checkPermission)
   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 MyCustomWindowsService.Monitor() in D:\...\MyCustomWindowsService.cs:line 207
   at MyCustomWindowsService.Start() in D:\...\MyCustomWindowsService.cs:line 178

在 ConfigurationManager 的深处......

4

1 回答 1

0

也许您的 XML 处理器忽略了 !ENTITY 声明,因为它们包含在原本为空的 DTD 中。

您是否有可用于验证此文档的 DTD?缺少 DTD 或模式,您不能真正说该文档是有效的。尝试通过在线 XML 验证服务运行它,例如 URL:http ://www.validome.org/xml/validate/

这是您的文档的修订版本,其中包含我制作的 DTD。看看这是否有帮助。


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration [
    <!ELEMENT configuration (configSections+, connectionStrings+, MyCustomSection)>

    <!ELEMENT configSections (section+)>

    <!ELEMENT section EMPTY>
    <!ATTLIST section name CDATA #REQUIRED>
    <!ATTLIST section type CDATA #REQUIRED>

    <!ELEMENT connectionStrings (add+)>

    <!ELEMENT add EMPTY>
    <!ATTLIST add name CDATA #REQUIRED>
    <!ATTLIST add providerName CDATA #REQUIRED>
    <!ATTLIST add connectionString CDATA #REQUIRED>

    <!ELEMENT MyCustomSection (#PCDATA)>

    <!ENTITY MyStorageLocation "\\MyServer\MyStorageFolder">
    <!ENTITY MyDatabaseServer "devdb01">
]>
<configuration>
  <configSections>
    <section name="MyCustomSection" type="MyCustomSectionHandler,MyAssembly"/>
  </configSections>
  <connectionStrings>
    <add name="MyConnectionString" providerName="System.Data.SqlClient" connectionString="Server=&MyDatabaseServer;;Database=MyDatabase;"/>
  </connectionStrings>
  <MyCustomSection>&MyStorageLocation;</MyCustomSection>
</configuration>
于 2009-05-09T09:18:42.567 回答