Error when registering custom config section
Hi All,
I have been trying to add a custom config section to SF4.1 using the example in the Developer Manual.
http://www.sitefinity.com/40/help/developers-guide/deep-dive-configuration-creating-configuration-classes.html
Regretfully I am running into a .net error when I add the following line for registering my config section to the Application_Start method of the global.asax.cs file.
protected void Application_Start(object sender, EventArgs e) Telerik.Sitefinity.Abstractions.Bootstrapper.Initialized += new EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized); Config.RegisterSection<Estate.Sitefinity4Extensions.Configuration.GoogleMaps.GoogleMapsConfig>();protected void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs args) Telerik.Sitefinity.Web.UI.Dialogs.RegisterDialog<Estate.Sitefinity4Extensions.Fields.ImageSelectorDialog>();Server Error in '/' Application.--------------------------------------------------------------------------------The type String cannot be constructed. You must configure the container to supply this value. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.InvalidOperationException: The type String cannot be constructed. You must configure the container to supply this value.Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [InvalidOperationException: The type String cannot be constructed. You must configure the container to supply this value.] Telerik.Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor) +277 Telerik.Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) +485 Telerik.Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +434 Telerik.Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) +400 Telerik.Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +222 Telerik.Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +434 Telerik.Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +318 BuildUp_Telerik.Sitefinity.Configuration.ConfigManager(IBuilderContext ) +216 Telerik.Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +304 Telerik.Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +434 Telerik.Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +440[ResolutionFailedException: Resolution of the dependency failed, type = "Telerik.Sitefinity.Configuration.ConfigManager", name = "XmlConfigProvider".Exception occurred while: while resolving.Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.-----------------------------------------------At the time of the exception, the container was: Resolving Telerik.Sitefinity.Configuration.ConfigManager,XmlConfigProvider Resolving parameter "providerName" of constructor Telerik.Sitefinity.Configuration.ConfigManager(System.String providerName) Resolving System.String,(none)] Telerik.Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +546 Telerik.Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides) +20 Telerik.Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, String name, ResolverOverride[] overrides) +91 Telerik.Sitefinity.Data.ManagerBase`1.GetManager(String providerName, String transactionName) +372 Telerik.Sitefinity.Services.InstallContext..ctor(String transactionName) +67 Telerik.Sitefinity.Services.SystemManager.Initialize() +255 Telerik.Sitefinity.Abstractions.Bootstrapper.RegisterRoutes(RouteCollection routes) +258 Telerik.Sitefinity.Abstractions.Bootstrapper.Bootstrap() +403 Telerik.Sitefinity.Web.SitefinityHttpModule.Init(HttpApplication context) +113 System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +582 System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +352 System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +405 System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +368[HttpException (0x80004005): Resolution of the dependency failed, type = "Telerik.Sitefinity.Configuration.ConfigManager", name = "XmlConfigProvider".Exception occurred while: while resolving.Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.-----------------------------------------------At the time of the exception, the container was: Resolving Telerik.Sitefinity.Configuration.ConfigManager,XmlConfigProvider Resolving parameter "providerName" of constructor Telerik.Sitefinity.Configuration.ConfigManager(System.String providerName) Resolving System.String,(none)] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +646 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +771 --------------------------------------------------------------------------------Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1Hello David Van Geel,
The code from our documentation needs to be slightly modified in order to work.
In the Global.asax you need to have:
protected void Application_Start(object sender, EventArgs e) Bootstrapper.Initialized += new EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized); void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e) if (e.CommandName == "Bootstrapped") Config.RegisterSection<CarsConfig>(); public class CarsConfig : ConfigSection [ConfigurationProperty("x", DefaultValue = "Def", IsRequired = false)] [ObjectInfo(typeof(ConfigDescriptions), Title = "xx", Description = "xx")] public string x get return this["x"].ToString(); set this["x"] = value; /// <summary> /// Gets a collection of user-defined parameters for the provider. /// </summary> [ConfigurationProperty("parameters")] public NameValueCollection Parameters get return (NameValueCollection)this["parameters"]; set this["parameters"] = value; ///// <summary> ///// Gets or sets the programmatic name of the toolbox item. ///// </summary> ///// <value>The name.</value> [ConfigurationProperty("name", DefaultValue = "", IsKey = true)] [ObjectInfo(typeof(ConfigDescriptions), Title = "ItemNameCaption", Description = "ItemName")] public string Name get return (string)this["name"]; set this["name"] = value; [ConfigurationProperty("new")] [ObjectInfo(typeof(ConfigDescriptions), Title = "New", Description = "New")] [ConfigurationCollection(typeof(CarSettings), AddItemName = "new")] public ConfigElementDictionary<string, CarSettings> New get return (ConfigElementDictionary<string, CarSettings>)this["new"]; [ConfigurationProperty("old")] [ObjectInfo(typeof(ConfigDescriptions), Title = "Old", Description = "Old")] [ConfigurationCollection(typeof(CarSettings), AddItemName = "old")] public ConfigElementDictionary<string, CarSettings> Old get return (ConfigElementDictionary<string, CarSettings>)this["old"]; protected override void OnPropertiesInitialized() base.OnPropertiesInitialized(); this.New.Add(new CarSettings(this.New) Name = "BMW", Year = 2010 ); // reference - MSDN http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx [ConfigurationProperty("version", DefaultValue = null)] [TypeConverter(typeof(StringVersionConverter))] [ObjectInfo(typeof(ConfigDescriptions), Title = "VersionAttributeTitle", Description = "VersionAttributeDescription")] public Version Version get return (Version)this["version"]; set this["version"] = value; IDictionary<string, string> d; ICollection<string> c; public class CarSettings : ConfigElement // You must have a constructor with ConfigElement parameter that accepts the parent public CarSettings(ConfigElement parent) : base(parent) [ConfigurationProperty("name", DefaultValue = "", IsRequired = true, IsKey = true)] public string Name get return (string)this["name"]; set this["name"] = value; [ConfigurationProperty("year", DefaultValue = 0, IsRequired = true)] public int Year get return (int)this["year"]; set this["year"] = value; Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Sorry Victor,
That didn't help much. Anyway I got a bit further by adding a resource class with texts for a title and description for each of the properties in the associated configsection class.
So in the configsection class I have something like this.
[ConfigurationProperty("apikey", DefaultValue = "", IsRequired = true)][ObjectInfo(typeof(GoogleMapsConfigDescriptions), Title = "ApiKeyTitle", Description = "ApiKeyDescription")]public string ApiKey get return this["apikey"].ToString(); set this["apikey"] = value; [ResourceEntry("ApiKeyDescription", Value = "The API key.", Description = "The description of API key field.", LastModified = "2011/08/31")]public string ApiKeyDescription get return this["ApiKeyDescription"]; [ResourceEntry("ApiKeyTitle", Value = "API key", Description = "The title of API key field.", LastModified = "2011/08/31")]public string ApiKeyTitle get return this["ApiKeyTitle"]; Property accessor 'Parameters' on object 'Estate.Sitefinity4Extensions.Configuration.GoogleMaps.GoogleMapsConfig' threw the following exception:'Config element null instance'/// <summary>/// Gets a collection of user-defined parameters for the provider./// </summary>[ConfigurationProperty("parameters")]public NameValueCollection Parameters get return (NameValueCollection)this["parameters"]; <!------ this line generates the error. set this["parameters"] = value; namespace Estate.Sitefinity4Extensions.Configuration.GoogleMaps using System; using System.Collections.Specialized; using System.ComponentModel; using System.Configuration; using Telerik.Sitefinity.Configuration; using Telerik.Sitefinity.Localization; using Telerik.Sitefinity.Utilities.TypeConverters; using Telerik.Sitefinity.Web.Configuration; using System.Collections.Generic; public class GoogleMapsConfig : ConfigSection public string ApiUrl get return "http://maps.google.com/maps?file=api&v=2"; [ConfigurationProperty("apikey", DefaultValue = "", IsRequired = true)] [ObjectInfo(typeof(GoogleMapsConfigDescriptions), Title = "ApiKeyTitle", Description = "ApiKeyDescription")] public string ApiKey get return this["apikey"].ToString(); set this["apikey"] = value; [ConfigurationProperty("url", DefaultValue = "", IsRequired = true)] [ObjectInfo(typeof(GoogleMapsConfigDescriptions), Title = "UrlTitle", Description = "UrlDescription")] public string Url get return this["url"].ToString(); set this["url"] = value; /// <summary> /// Gets a collection of user-defined parameters for the provider. /// </summary> [ConfigurationProperty("parameters")] public NameValueCollection Parameters get return (NameValueCollection)this["parameters"]; set this["parameters"] = value; [ConfigurationProperty("New")] [ObjectInfo(typeof(GoogleMapsConfigDescriptions), Title = "NewTitle", Description = "NewDescription")] [ConfigurationCollection(typeof(GoogleMapsSettings), AddItemName = "New")] public ConfigElementDictionary<string, GoogleMapsSettings> New get return (ConfigElementDictionary<string, GoogleMapsSettings>)this["new"]; [ConfigurationProperty("Old")] [ObjectInfo(typeof(GoogleMapsConfigDescriptions), Title = "OldTitle", Description = "OldDescription")] [ConfigurationCollection(typeof(GoogleMapsSettings), AddItemName = "Old")] public ConfigElementDictionary<string, GoogleMapsSettings> Old get return (ConfigElementDictionary<string, GoogleMapsSettings>)this["old"]; protected override void OnPropertiesInitialized() base.OnPropertiesInitialized(); this.New.Add(new GoogleMapsSettings(this.New) Url = "Website", Apikey = "Not set" ); [ConfigurationProperty("version", DefaultValue = null)] [TypeConverter(typeof(StringVersionConverter))] [ObjectInfo(typeof(ConfigDescriptions), Title = "VersionAttributeTitle", Description = "VersionAttributeDescription")] public Version Version get return (Version)this["version"]; set this["version"] = value; IDictionary<string, string> d; ICollection<string> c; namespace Estate.Sitefinity4Extensions.Configuration.GoogleMaps using System.Configuration; using Telerik.Sitefinity.Configuration; public class GoogleMapsSettings : ConfigElement public GoogleMapsSettings(ConfigElement parent) : base(parent) [ConfigurationProperty("apikey", DefaultValue = "", IsRequired = true)] public string Apikey get return (string)this["apikey"]; set this["apikey"] = value; [ConfigurationProperty("url", DefaultValue = "", IsRequired = true, IsKey = true)] public string Url get return (string)this["url"]; set this["url"] = value; Hello David Van Geel,
Can you open a support ticket and submit all files related to the custom configuration so we can try and set it up locally.
Kind regards,
Victor Velev
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>