1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Configuration.Internal; 6 using System.Diagnostics; 7 8 namespace System.Configuration 9 { 10 public sealed class SectionInformation 11 { 12 // Flags 13 private const int FlagAttached = 0x00000001; 14 private const int FlagDeclared = 0x00000002; 15 private const int FlagDeclarationRequired = 0x00000004; 16 private const int FlagAllowLocation = 0x00000008; 17 private const int FlagRestartOnExternalChanges = 0x00000010; 18 private const int FlagRequirePermission = 0x00000020; 19 private const int FlagLocationLocked = 0x00000040; 20 private const int FlagChildrenLocked = 0x00000080; 21 private const int FlagInheritInChildApps = 0x00000100; 22 private const int FlagIsParentSection = 0x00000200; 23 private const int FlagRemoved = 0x00000400; 24 private const int FlagProtectionProviderDetermined = 0x00000800; 25 private const int FlagForceSave = 0x00001000; 26 private const int FlagIsUndeclared = 0x00002000; 27 private const int FlagChildrenLockWithoutFileInput = 0x00004000; 28 29 private const int FlagAllowExeDefinitionModified = 0x00010000; 30 private const int FlagAllowDefinitionModified = 0x00020000; 31 private const int FlagConfigSourceModified = 0x00040000; 32 private const int FlagProtectionProviderModified = 0x00080000; 33 private const int FlagOverrideModeDefaultModified = 0x00100000; 34 private const int FlagOverrideModeModified = 0x00200000; // Used only for modified tracking 35 36 private readonly ConfigurationSection _configurationSection; 37 private ConfigurationAllowDefinition _allowDefinition; 38 private ConfigurationAllowExeDefinition _allowExeDefinition; 39 private MgmtConfigurationRecord _configRecord; 40 private string _configSource; 41 private SafeBitVector32 _flags; 42 private SimpleBitVector32 _modifiedFlags; 43 private OverrideModeSetting _overrideMode; // The override mode at the current config path 44 private OverrideModeSetting _overrideModeDefault; // The default mode for the section in _configurationSection 45 private ProtectedConfigurationProvider _protectionProvider; 46 private string _typeName; 47 SectionInformation(ConfigurationSection associatedConfigurationSection)48 internal SectionInformation(ConfigurationSection associatedConfigurationSection) 49 { 50 ConfigKey = string.Empty; 51 Name = string.Empty; 52 53 _configurationSection = associatedConfigurationSection; 54 _allowDefinition = ConfigurationAllowDefinition.Everywhere; 55 _allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication; 56 _overrideModeDefault = OverrideModeSetting.s_sectionDefault; 57 _overrideMode = OverrideModeSetting.s_locationDefault; 58 59 _flags[FlagAllowLocation] = true; 60 _flags[FlagRestartOnExternalChanges] = true; 61 _flags[FlagRequirePermission] = true; 62 _flags[FlagInheritInChildApps] = true; 63 _flags[FlagForceSave] = false; 64 65 _modifiedFlags = new SimpleBitVector32(); 66 } 67 68 private bool IsRuntime => _flags[FlagAttached] && 69 (_configRecord == null); 70 71 internal bool Attached => _flags[FlagAttached]; 72 73 internal string ConfigKey { get; private set; } 74 75 internal bool Removed 76 { 77 get { return _flags[FlagRemoved]; } 78 set { _flags[FlagRemoved] = value; } 79 } 80 81 public string SectionName => ConfigKey; 82 83 public string Name { get; private set; } 84 85 public ConfigurationAllowDefinition AllowDefinition 86 { 87 get { return _allowDefinition; } 88 set 89 { 90 VerifyIsEditable(); 91 VerifyIsEditableFactory(); 92 93 // allow AllowDefinition to be different from current type, 94 // so long as it doesn't conflict with a type already defined 95 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 96 if ((factoryRecord != null) && (factoryRecord.AllowDefinition != value)) 97 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 98 99 _allowDefinition = value; 100 _modifiedFlags[FlagAllowDefinitionModified] = true; 101 } 102 } 103 104 internal bool AllowDefinitionModified => _modifiedFlags[FlagAllowDefinitionModified]; 105 106 public ConfigurationAllowExeDefinition AllowExeDefinition 107 { 108 get { return _allowExeDefinition; } 109 set 110 { 111 VerifyIsEditable(); 112 VerifyIsEditableFactory(); 113 114 // allow AllowDefinition to be different from current type, 115 // so long as it doesn't conflict with a type already defined 116 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 117 if ((factoryRecord != null) && (factoryRecord.AllowExeDefinition != value)) 118 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 119 120 _allowExeDefinition = value; 121 _modifiedFlags[FlagAllowExeDefinitionModified] = true; 122 } 123 } 124 125 internal bool AllowExeDefinitionModified => _modifiedFlags[FlagAllowExeDefinitionModified]; 126 127 public OverrideMode OverrideModeDefault 128 { 129 get { return _overrideModeDefault.OverrideMode; } 130 set 131 { 132 VerifyIsEditable(); 133 VerifyIsEditableFactory(); 134 135 // allow OverrideModeDefault to be different from current value, 136 // so long as it doesn't conflict with a type already defined 137 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 138 if ((factoryRecord != null) && (factoryRecord.OverrideModeDefault.OverrideMode != value)) 139 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 140 141 // Threat "Inherit" as "Allow" as "Inherit" does not make sense as a default 142 if (value == OverrideMode.Inherit) value = OverrideMode.Allow; 143 144 _overrideModeDefault.OverrideMode = value; 145 _modifiedFlags[FlagOverrideModeDefaultModified] = true; 146 } 147 } 148 149 internal OverrideModeSetting OverrideModeDefaultSetting => _overrideModeDefault; 150 151 internal bool OverrideModeDefaultModified => _modifiedFlags[FlagOverrideModeDefaultModified]; 152 153 public bool AllowLocation 154 { 155 get { return _flags[FlagAllowLocation]; } 156 set 157 { 158 VerifyIsEditable(); 159 VerifyIsEditableFactory(); 160 161 // allow AllowLocation to be different from current type, 162 // so long as it doesn't conflict with a type already defined 163 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 164 if ((factoryRecord != null) && (factoryRecord.AllowLocation != value)) 165 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 166 167 _flags[FlagAllowLocation] = value; 168 _modifiedFlags[FlagAllowLocation] = true; 169 } 170 } 171 172 internal bool AllowLocationModified => _modifiedFlags[FlagAllowLocation]; 173 174 public bool AllowOverride 175 { 176 get { return _overrideMode.AllowOverride; } 177 set 178 { 179 VerifyIsEditable(); 180 VerifySupportsLocation(); 181 _overrideMode.AllowOverride = value; 182 _modifiedFlags[FlagOverrideModeModified] = true; 183 } 184 } 185 186 public OverrideMode OverrideMode 187 { 188 get { return _overrideMode.OverrideMode; } 189 set 190 { 191 VerifyIsEditable(); 192 VerifySupportsLocation(); 193 _overrideMode.OverrideMode = value; 194 _modifiedFlags[FlagOverrideModeModified] = true; 195 196 // Modify the state of OverrideModeEffective according to the changes to the current mode 197 switch (value) 198 { 199 case OverrideMode.Inherit: 200 // Wehen the state is changing to inherit - apply the value from parent which does not 201 // include the file input lock mode 202 _flags[FlagChildrenLocked] = _flags[FlagChildrenLockWithoutFileInput]; 203 break; 204 case OverrideMode.Allow: 205 _flags[FlagChildrenLocked] = false; 206 break; 207 case OverrideMode.Deny: 208 _flags[FlagChildrenLocked] = true; 209 break; 210 default: 211 Debug.Assert(false, "Unexpected value for OverrideMode"); 212 break; 213 } 214 } 215 } 216 217 public OverrideMode OverrideModeEffective => _flags[FlagChildrenLocked] ? OverrideMode.Deny : OverrideMode.Allow 218 ; 219 220 internal OverrideModeSetting OverrideModeSetting => _overrideMode; 221 222 223 // LocationAttributesAreDefault 224 // 225 // Are the location attributes for this section set to the 226 // default settings? 227 internal bool LocationAttributesAreDefault => _overrideMode.IsDefaultForLocationTag && 228 _flags[FlagInheritInChildApps]; 229 230 public string ConfigSource 231 { 232 get { return _configSource ?? string.Empty; } 233 set 234 { 235 VerifyIsEditable(); 236 237 string configSource = !string.IsNullOrEmpty(value) 238 ? BaseConfigurationRecord.NormalizeConfigSource(value, null) 239 : null; 240 241 // return early if there is no change 242 if (configSource == _configSource) 243 return; 244 245 _configRecord?.ChangeConfigSource(this, _configSource, ConfigSourceStreamName, configSource); 246 247 _configSource = configSource; 248 _modifiedFlags[FlagConfigSourceModified] = true; 249 } 250 } 251 252 internal bool ConfigSourceModified => _modifiedFlags[FlagConfigSourceModified]; 253 254 internal string ConfigSourceStreamName { get; set; } 255 256 public bool InheritInChildApplications 257 { 258 get { return _flags[FlagInheritInChildApps]; } 259 set 260 { 261 VerifyIsEditable(); 262 VerifySupportsLocation(); 263 _flags[FlagInheritInChildApps] = value; 264 } 265 } 266 267 // True if the section is declared at the current level 268 public bool IsDeclared 269 { 270 get 271 { 272 VerifyNotParentSection(); 273 274 return _flags[FlagDeclared]; 275 } 276 } 277 278 // Is the Declaration Required. It is required if it is not set 279 // in a parent, or the parent entry does not have the type 280 public bool IsDeclarationRequired 281 { 282 get 283 { 284 VerifyNotParentSection(); 285 286 return _flags[FlagDeclarationRequired]; 287 } 288 } 289 290 // Is the Definition Allowed at this point. This is all depending 291 // on the Definition that is allowed, and what context we are 292 // writing the file 293 private bool IsDefinitionAllowed 294 => (_configRecord == null) || _configRecord.IsDefinitionAllowed(_allowDefinition, _allowExeDefinition); 295 296 public bool IsLocked => _flags[FlagLocationLocked] || !IsDefinitionAllowed || 297 _configurationSection.ElementInformation.IsLocked; 298 299 public bool IsProtected => ProtectionProvider != null; 300 301 public ProtectedConfigurationProvider ProtectionProvider 302 { 303 get 304 { 305 if (!_flags[FlagProtectionProviderDetermined] && (_configRecord != null)) 306 { 307 _protectionProvider = _configRecord.GetProtectionProviderFromName(ProtectionProviderName, false); 308 _flags[FlagProtectionProviderDetermined] = true; 309 } 310 311 return _protectionProvider; 312 } 313 } 314 315 internal string ProtectionProviderName { get; private set; } 316 317 public bool RestartOnExternalChanges 318 { 319 get { return _flags[FlagRestartOnExternalChanges]; } 320 set 321 { 322 VerifyIsEditable(); 323 VerifyIsEditableFactory(); 324 325 // allow RestartOnExternalChanges to be different from current type, 326 // so long as it doesn't conflict with a type already defined 327 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 328 if ((factoryRecord != null) && (factoryRecord.RestartOnExternalChanges != value)) 329 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 330 331 _flags[FlagRestartOnExternalChanges] = value; 332 _modifiedFlags[FlagRestartOnExternalChanges] = true; 333 } 334 } 335 336 internal bool RestartOnExternalChangesModified => _modifiedFlags[FlagRestartOnExternalChanges]; 337 338 public bool RequirePermission 339 { 340 get { return _flags[FlagRequirePermission]; } 341 set 342 { 343 VerifyIsEditable(); 344 VerifyIsEditableFactory(); 345 346 // allow RequirePermission to be different from current type, 347 // so long as it doesn't conflict with a type already defined 348 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 349 if ((factoryRecord != null) && (factoryRecord.RequirePermission != value)) 350 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey)); 351 352 _flags[FlagRequirePermission] = value; 353 _modifiedFlags[FlagRequirePermission] = true; 354 } 355 } 356 357 internal bool RequirePermissionModified => _modifiedFlags[FlagRequirePermission]; 358 359 360 public string Type 361 { 362 get { return _typeName; } 363 set 364 { 365 if (string.IsNullOrEmpty(value)) throw ExceptionUtil.PropertyNullOrEmpty(nameof(Type)); 366 367 VerifyIsEditable(); 368 VerifyIsEditableFactory(); 369 370 // allow type to be different from current type, 371 // so long as it doesn't conflict with a type already defined 372 FactoryRecord factoryRecord = FindParentFactoryRecord(false); 373 if (factoryRecord != null) 374 { 375 IInternalConfigHost host = null; 376 if (_configRecord != null) host = _configRecord.Host; 377 378 if (!factoryRecord.IsEquivalentType(host, value)) 379 { 380 throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, 381 ConfigKey)); 382 } 383 } 384 385 _typeName = value; 386 } 387 } 388 389 internal string RawXml { get; set; } 390 391 // True if the section will be serialized to the current hierarchy level, regardless of 392 // ConfigurationSaveMode. 393 public bool ForceSave 394 { 395 get { return _flags[FlagForceSave]; } 396 set 397 { 398 VerifyIsEditable(); 399 400 _flags[FlagForceSave] = value; 401 } 402 } 403 ResetModifiedFlags()404 internal void ResetModifiedFlags() 405 { 406 _modifiedFlags = new SimpleBitVector32(); 407 } 408 IsModifiedFlags()409 internal bool IsModifiedFlags() 410 { 411 return _modifiedFlags.Data != 0; 412 } 413 414 // for instantiation of a ConfigurationSection from GetConfig AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord)415 internal void AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord, 416 SectionRecord sectionRecord) 417 { 418 SetRuntimeConfigurationInformation(configRecord, factoryRecord, sectionRecord); 419 _configRecord = configRecord; 420 } 421 SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord)422 internal void SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord, 423 FactoryRecord factoryRecord, SectionRecord sectionRecord) 424 { 425 _flags[FlagAttached] = true; 426 427 // factory info 428 ConfigKey = factoryRecord.ConfigKey; 429 Name = factoryRecord.Name; 430 _typeName = factoryRecord.FactoryTypeName; 431 _allowDefinition = factoryRecord.AllowDefinition; 432 _allowExeDefinition = factoryRecord.AllowExeDefinition; 433 _flags[FlagAllowLocation] = factoryRecord.AllowLocation; 434 _flags[FlagRestartOnExternalChanges] = factoryRecord.RestartOnExternalChanges; 435 _flags[FlagRequirePermission] = factoryRecord.RequirePermission; 436 _overrideModeDefault = factoryRecord.OverrideModeDefault; 437 438 if (factoryRecord.IsUndeclared) 439 { 440 _flags[FlagIsUndeclared] = true; 441 _flags[FlagDeclared] = false; 442 _flags[FlagDeclarationRequired] = false; 443 } 444 else 445 { 446 _flags[FlagIsUndeclared] = false; 447 _flags[FlagDeclared] = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, false) != null; 448 _flags[FlagDeclarationRequired] = configRecord.IsRootDeclaration(factoryRecord.ConfigKey, false); 449 } 450 451 // section info 452 _flags[FlagLocationLocked] = sectionRecord.Locked; 453 _flags[FlagChildrenLocked] = sectionRecord.LockChildren; 454 _flags[FlagChildrenLockWithoutFileInput] = sectionRecord.LockChildrenWithoutFileInput; 455 456 if (sectionRecord.HasFileInput) 457 { 458 SectionInput fileInput = sectionRecord.FileInput; 459 460 _flags[FlagProtectionProviderDetermined] = fileInput.IsProtectionProviderDetermined; 461 _protectionProvider = fileInput.ProtectionProvider; 462 463 SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo; 464 465 _configSource = sectionXmlInfo.ConfigSource; 466 ConfigSourceStreamName = sectionXmlInfo.ConfigSourceStreamName; 467 _overrideMode = sectionXmlInfo.OverrideModeSetting; 468 _flags[FlagInheritInChildApps] = !sectionXmlInfo.SkipInChildApps; 469 ProtectionProviderName = sectionXmlInfo.ProtectionProviderName; 470 } 471 else 472 { 473 _flags[FlagProtectionProviderDetermined] = false; 474 _protectionProvider = null; 475 } 476 477 // element context information 478 _configurationSection.AssociateContext(configRecord); 479 } 480 DetachFromConfigurationRecord()481 internal void DetachFromConfigurationRecord() 482 { 483 RevertToParent(); 484 _flags[FlagAttached] = false; 485 _configRecord = null; 486 } 487 VerifyDesigntime()488 private void VerifyDesigntime() 489 { 490 if (IsRuntime) throw new InvalidOperationException(SR.Config_operation_not_runtime); 491 } 492 VerifyIsAttachedToConfigRecord()493 private void VerifyIsAttachedToConfigRecord() 494 { 495 if (_configRecord == null) 496 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_not_attached); 497 } 498 499 // VerifyIsEditable 500 // 501 // Verify the section is Editable. 502 // It may not be editable for the following reasons: 503 // - We are in Runtime mode, not Design time 504 // - The section is not attached to a _configRecord. 505 // - We are locked (ie. allowOveride = false ) 506 // - We are a parent section (ie. Retrieved from GetParentSection) 507 // VerifyIsEditable()508 internal void VerifyIsEditable() 509 { 510 VerifyDesigntime(); 511 512 if (IsLocked) 513 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_locked); 514 515 if (_flags[FlagIsParentSection]) 516 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_parentsection); 517 518 if (!_flags[FlagAllowLocation] && 519 (_configRecord != null) && 520 _configRecord.IsLocationConfig) 521 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_location_locked); 522 } 523 VerifyNotParentSection()524 private void VerifyNotParentSection() 525 { 526 if (_flags[FlagIsParentSection]) 527 throw new InvalidOperationException(SR.Config_configsection_parentnotvalid); 528 } 529 530 // Verify that we support the location tag. This is true either 531 // in machine.config, or in any place for the web config system VerifySupportsLocation()532 private void VerifySupportsLocation() 533 { 534 if ((_configRecord != null) && 535 !_configRecord.RecordSupportsLocation) 536 throw new InvalidOperationException(SR.Config_cannot_edit_locationattriubtes); 537 } 538 VerifyIsEditableFactory()539 internal void VerifyIsEditableFactory() 540 { 541 if ((_configRecord != null) && _configRecord.IsLocationConfig) 542 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_in_location_config); 543 544 // Can't edit factory if the section is built-in 545 if (BaseConfigurationRecord.IsImplicitSection(ConfigKey)) 546 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_implicit); 547 548 // Can't edit undeclared section 549 if (_flags[FlagIsUndeclared]) 550 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_undeclared); 551 } 552 FindParentFactoryRecord(bool permitErrors)553 private FactoryRecord FindParentFactoryRecord(bool permitErrors) 554 { 555 FactoryRecord factoryRecord = null; 556 557 if ((_configRecord != null) && !_configRecord.Parent.IsRootConfig) 558 factoryRecord = _configRecord.Parent.FindFactoryRecord(ConfigKey, permitErrors); 559 560 return factoryRecord; 561 } 562 563 // Force the section declaration to be written out during Save. ForceDeclaration()564 public void ForceDeclaration() 565 { 566 ForceDeclaration(true); 567 } 568 569 // If force==false, it actually means don't declare it at 570 // the current level. ForceDeclaration(bool force)571 public void ForceDeclaration(bool force) 572 { 573 VerifyIsEditable(); 574 575 if ((force == false) && 576 _flags[FlagDeclarationRequired]) 577 { 578 // Since it is required, we can not remove it 579 } 580 else 581 { 582 // CONSIDER: There is no apriori way to determine if a section 583 // is implicit or undeclared. Would it be better to simply 584 // fail silently so that app code can easily loop through sections 585 // and declare all of them? 586 if (force && BaseConfigurationRecord.IsImplicitSection(SectionName)) 587 throw new ConfigurationErrorsException(SR.Cannot_declare_or_remove_implicit_section); 588 589 if (force && _flags[FlagIsUndeclared]) 590 { 591 throw new ConfigurationErrorsException( 592 SR.Config_cannot_edit_configurationsection_when_it_is_undeclared); 593 } 594 595 _flags[FlagDeclared] = force; 596 } 597 } 598 599 // method to cause a section to be protected using the specified provider ProtectSection(string protectionProvider)600 public void ProtectSection(string protectionProvider) 601 { 602 ProtectedConfigurationProvider protectedConfigurationProvider; 603 604 VerifyIsEditable(); 605 606 // Do not encrypt sections that will be read by a native reader. 607 // These sections are be marked with allowLocation=false. 608 // Also, the configProtectedData section cannot be encrypted! 609 if (!AllowLocation || (ConfigKey == BaseConfigurationRecord.ReservedSectionProtectedConfiguration)) 610 throw new InvalidOperationException(SR.Config_not_allowed_to_encrypt_this_section); 611 612 if (_configRecord != null) 613 { 614 if (string.IsNullOrEmpty(protectionProvider)) protectionProvider = _configRecord.DefaultProviderName; 615 616 protectedConfigurationProvider = _configRecord.GetProtectionProviderFromName(protectionProvider, true); 617 } 618 else throw new InvalidOperationException(SR.Must_add_to_config_before_protecting_it); 619 620 ProtectionProviderName = protectionProvider; 621 _protectionProvider = protectedConfigurationProvider; 622 623 _flags[FlagProtectionProviderDetermined] = true; 624 _modifiedFlags[FlagProtectionProviderModified] = true; 625 } 626 UnprotectSection()627 public void UnprotectSection() 628 { 629 VerifyIsEditable(); 630 631 _protectionProvider = null; 632 ProtectionProviderName = null; 633 _flags[FlagProtectionProviderDetermined] = true; 634 _modifiedFlags[FlagProtectionProviderModified] = true; 635 } 636 GetParentSection()637 public ConfigurationSection GetParentSection() 638 { 639 VerifyDesigntime(); 640 641 if (_flags[FlagIsParentSection]) 642 throw new InvalidOperationException(SR.Config_getparentconfigurationsection_first_instance); 643 644 // if a users create a configsection with : sectionType sec = new sectionType(); 645 // the config record will be null. Return null for the parent in this case. 646 ConfigurationSection ancestor = null; 647 if (_configRecord != null) 648 { 649 ancestor = _configRecord.FindAndCloneImmediateParentSection(_configurationSection); 650 if (ancestor != null) 651 { 652 ancestor.SectionInformation._flags[FlagIsParentSection] = true; 653 ancestor.SetReadOnly(); 654 } 655 } 656 657 return ancestor; 658 } 659 GetRawXml()660 public string GetRawXml() 661 { 662 VerifyDesigntime(); 663 VerifyNotParentSection(); 664 665 return RawXml ?? _configRecord?.GetRawXml(ConfigKey); 666 } 667 SetRawXml(string rawXml)668 public void SetRawXml(string rawXml) 669 { 670 VerifyIsEditable(); 671 672 if (_configRecord != null) _configRecord.SetRawXml(_configurationSection, rawXml); 673 else RawXml = string.IsNullOrEmpty(rawXml) ? null : rawXml; 674 } 675 RevertToParent()676 public void RevertToParent() 677 { 678 VerifyIsEditable(); 679 VerifyIsAttachedToConfigRecord(); 680 681 _configRecord.RevertToParent(_configurationSection); 682 } 683 } 684 }