Misfit Geek

Fustrated by Design !

MaximumASP

While getting started on .NETOOP, one of the first issues to address is that of “Global” settings.

When you build a web application for a single purpose, you can hard-code things without much concern.

Microsoft.com is probably always going to have the same name, but .NETOOP is going to be a portal application. Everyone who uses the application will need to .NETOOP to use their own web site name (and lots of other site specific configuration data.)

Now ASP.NET has that clever “Application Settings” feature. This is a great feature that includes design time setting creating and a well factored API for reading the settings.

The problem is that these settings like “Site Name” are going to be used all over the site and the actual settings are stored in the web.config file.

Reading the .xml file several times for each page lifecycle would be VERY bad for performance.

By the way, if your worried about WRITING to the web.config file, you are right. When you save changes to a web.config file the application needs to be reset, so you defiantly do not want to do much writing to the web.config file since it will kill performance and screw up session state for in session users.

In our case we are talking about global configuration settings which will be set up when the site is originally configured and will very seldom, if ever, be changed after deployment. So the write issue is a moot point for our requirements but the READ FREQUENCY is still a big issue.

As we’re building .NETOOP we really want to take advantage of ASP.NET services, but we want the application to scale VERY well.

At first I thought perhaps the right solution was to implement a new Settings Provider that uses SQL Server as described [ HERE ]

We’ll probably have to revisit the custom provider when we implement profiles but it seemed over kill for our needs and I think I’ve implemented a better solution with less work.

Innate property caching !

Given the application settings in the following web.config snippet……

<appSettings>
<add key="SiteName" value="NETOOP Site Name" />
<add key="SiteOwner" value="NETOOP Site Owner" />
</appSettings>

Comments

There are 43 comments for this post.

  1. Muhammad Mosa on July 6, 2009 9:44 am

    I just wanted to highlight something about the settings! few things should not be considered as settings! such as site name, which here demonstrated to be used as Site Title. This string could be localized. And so it should be stored in some other proper place and not in configuration.

    Just to highlight the difference between settings and localizable literals that can be confused with settings.

  2. Darnell on July 6, 2009 9:46 am

    Well, that’s your OPINION.

  3. Global Application settings and the web.config file. : Misfit Geek on July 6, 2009 9:46 am

    RE: Global Application settings and the web.config file.

    Thank you for submitting this cool story – Trackback from DotNetShoutout

  4. Johnny on July 6, 2009 10:18 am

    Excellent post Joe. Totally agree on that approach right there. For those settings in web.config that we hardly ever change a static class is the better solution.

    Cheers

  5. Henrik Juhlin on July 6, 2009 10:47 am

    Whoaa… I’m impressed. I have always been thinking of web.config of a good place to put stuffs like this and that is was cached in memory or something. But after some tests I did, I have found out that this is about 10-15 times faster for each read. And that’s for every read, so doing this for example “for (int i = 0; i < 10000000; i++) { Page.Header.Title = WebConfigurationManager.AppSettings.Get("SiteName"); }”

    takes 15 sec! Doing the same with your version takes 0.3 sec. Getting the value one time form web.config takes 00:00:00.0000181 and one time from your version takes 00:00:00.0000011

    But then I can’t understand why the web.config settings isnt cached. Guess it’s the same for connection strings, and they are often used on all pages and on some pages more the once.

  6. Global Application settings and the web.config file. : Misfit Geek on July 6, 2009 10:55 am

    RE: Global Application settings and the web.config file.

    Pingback from Global Application settings and the web.config file. : Misfit Geek

  7. Global Application settings and the web.config file. | I love .NET! on July 6, 2009 11:17 am

    RE: Global Application settings and the web.config file.

    Pingback from Global Application settings and the web.config file. | I love .NET!

  8. Subbaraokv on July 6, 2009 11:39 am

    Great article ! I have a question though, how do we address the encryption and decryption of key value data that we store in appSettings

  9. Global Application settings and the web.config file. | Nexo IT - Information Technology News on July 6, 2009 11:49 am

    RE: Global Application settings and the web.config file.

    Pingback from Global Application settings and the web.config file. | Nexo IT – Information Technology News

  10. Global Application settings and the web.config file. | Nexo IT - Information Technology News on July 6, 2009 11:49 am

    RE: Global Application settings and the web.config file.

    Pingback from Global Application settings and the web.config file. | Nexo IT – Information Technology News

  11. Richard on July 6, 2009 12:17 pm

    @Henrik

    I always believed as you that .config settings are cached as this article <http://msdn.microsoft.com/en-us/library/aa719558(VS.71).aspx> on the MSDN site indicates (the item is under .NET Framework 1.1 so the assumption is that MS did not "uncache" the settings in a subsequent framework version). I have seen elsewhere that web resources are not cached when debug="true" is set in web.config. I was curious how the debug flag was set during your tests and if you have tried the same tests with the debug flag set to both true and false to see if there is any difference?

  12. Henrik Juhlin on July 6, 2009 1:39 pm

    @Richard

    I did have it at <compilation debug="false"> before and tested to change it do true now. Page.Header.Title = WebConfigurationManager.AppSettings.Get("SiteName"); stayed the same, but the Page.Header.Title = SiteGlobalSettings.MySiteName; did go up a with like 30%, but still, the SiteGlobalSettings are around 7-8 times faster.

  13. Global Application settings and the web.config file. : Misfit Geek on July 6, 2009 2:37 pm

    RE: Global Application settings and the web.config file.

    Pingback from Global Application settings and the web.config file. : Misfit Geek

  14. Bernie Basel on July 6, 2009 3:43 pm

    I’m interested in the decision not to use application variables for this type of data. On my site I have code in the Global.asax that iterates though the AppSettings and create corresponding application variables at application start up. What does creating a static class buy you over the use of application variables?

  15. Johnny Nouel on July 6, 2009 3:46 pm

    Now I have a question:

    How long does that little Settings class is being kept in cache before it goes to read again from web.config file in disk?

  16. Joe Stagner on July 6, 2009 4:54 pm

    Johnny – The Static Class will stay in memory as long as the application does. When the application is removed from memory depends on the application, app pool, and IIS configureations but asa rule of thumb, it will be unloaded after 20 minutes with NO requests.

  17. Joe Stagner on July 6, 2009 5:02 pm

    Bernie,

    There are a couple of reasons that I choose not to use Application Object.

    Yhere might be quite a bit of data and Application Objects use Name/Value pairs.

    I don’t care for this style, types are not obvious, using user defined types are un-intuitive and lookup for very frequently accessed data items would cause a performance hit since the item needs to be located in the Applacation object collection before it’s value can be retrieved.

    Also, for SEO purposes I intend to use some of these values as root values and add some semi-static page specific data.

  18. Bernie Basel on July 6, 2009 5:46 pm

    By definition data retrieved from the Web.Config will be strings data. But I understand, I do some processing in the Application start like converting the connection string into a ConnectionString object. I was not aware of a performance hit using Name/Value pairs as opposed to retrieving a value from an object but it makes sense. I guess like most things I should create a test bed and take some timings.

  19. Joe Stagner on July 6, 2009 5:49 pm

    Bernie,

    One of the key points is that non string data will only be accessed ONCE as string data when retrieved form the config file but once stored as a static property it can be a member variable of any type.

  20. Lee Dumond on July 6, 2009 6:15 pm

    I kinda have to agree with the first comment.

    While there may be many values that this approach may be useful for, I would look into localization for storing string literals, rather than configuration.

  21. Joe Stagner on July 6, 2009 6:18 pm

    This is a single sample. There are many data items that may not be localizable. Agin, use the technique if it meets your needs,do something else if it doesn’t.

  22. Global Application settings and the web.config file. : Misfit Geek on July 6, 2009 6:42 pm

    RE: Global Application settings and the web.config file.

    Thank you for submitting this cool story – Trackback from ravipendigg

  23. The Technology Post for July 6th, 2009 | I love .NET! on July 6, 2009 9:03 pm

    RE: Global Application settings and the web.config file.

    Pingback from The Technology Post for July 6th, 2009 | I love .NET!

  24. The Technology Post for July 6th, 2009 | Nexo IT - Information Technology News on July 6, 2009 9:54 pm

    RE: Global Application settings and the web.config file.

    Pingback from The Technology Post for July 6th, 2009 | Nexo IT – Information Technology News

  25. Varun on July 7, 2009 4:39 am

    Nice approach Joe. Carry on, thanks.

  26. Adam Schroder on July 7, 2009 7:19 am

    I’ve been using the static variables approach with great success. Beats trying to put a wrapper around the Application variables or directly accessing the Application settings with magic strings.

    What do you guys do with user specific variables? Store them in the session?? retrieve them from the db when needed??

  27. The Technology Post for July 6th, 2009 | rapid-DEV.net on July 7, 2009 7:46 am

    RE: Global Application settings and the web.config file.

    Pingback from The Technology Post for July 6th, 2009 | rapid-DEV.net

  28. vijay on July 7, 2009 8:44 am

    Hi Joe,

    I have couple of questions to you. Assuming that we would not update the web.config file programmatically is there need for SiteGlobalSettings class. Because my understanding is that even the web.config file is cached when the application is loaded. Correct me if I am wrong.

    Do we need to check for null for each and every property acceess from SiteGlobalSettings class.

    Why are you hardcoding the "NETOOP – The .NET Object Oriented Portal" text in the else part. Should we throw an exception instead.

    Thanks,

    Vijay.

  29. Joe Stagner on July 7, 2009 8:46 am

    Hi Vijay,

    1.) My test showed the static value is faster. (plus all theother reasons I listed above.)

    2.) Yes

    3.) Becuase it’s a prototype

  30. Andy White on July 7, 2009 4:51 pm

    I think you are over engineering it.

  31. Raj Kaimal on July 7, 2009 4:53 pm

    >Reading the .xml file several times for each page lifecycle would be VERY bad for performance.

    Are you sure about this? I thought web.config was cached.

    From MSDN:

    These methods perform read-only operations, use a single ***cached*** instance of the configuration, and are multithread aware.

    http://msdn.microsoft.com/en-us/library/system.web.configuration.webconfigurationmanager(VS.80).aspx

    Regards,

    Raj

  32. Henrik Juhlin on July 7, 2009 6:14 pm

    @Raj I was sure about that to until I did a few tests:

    This takes 15 sec to run:

    for (int i = 0; i < 10000000; i++)

    {

    Page.Header.Title = WebConfigurationManager.AppSettings.Get("SiteName");

    }

    Doing the same with the static class takes 0.3 sec

  33. RN on July 7, 2009 9:00 pm

    First of All: Doesnt make sense to provide a Setter in the property.

    Second: It would be much easier to just add the static variable in a helper class, instead of creating a seperate class.

    public static HelperClass

    {

    public static string AppSetGetValue = ConfigurationManager.AppSettings["Name"];

    }

    Since Static variables will be initialized only once.

    Hope this helps..

    Thanks,

    RN

  34. Proving the performance of Static Properties. on July 8, 2009 8:39 am

    RE: Global Application settings and the web.config file.

    I don’t claim to be the best developer on the planet :) but I’m always amazed at how all the “experts” come out of the woodwork to posh on other peoples code :) Several folks have commented and emailed about hey the technique I posted earlier was unnecessary

  35. Vijay on July 8, 2009 9:38 am

    Joe,

    I dont think it is a good idea to check for null for each property access in SiteGlobalSettings class for the following reasons.

    1. There is no guarantee that every developer will check for null.

    2. We have to wirte more code.

    Instead i am suggesting the following strategy.

    public static class SiteGlobalSettings

    {

    static private string mySiteName;

    static public string MySiteName

    {

    get

    {

    if(null != mySiteName)

    return mySiteName;

    else

    throw Exception("Site name not set.");

    }

    set

    {

    mySiteName = value;

    }

    }

    static SiteGlobalSettings()

    {

    mySiteName = WebConfigurationManager.AppSettings.Get("SiteName");

    }

    }

    This way we don’t have to check for null for each propery access. We can simply call SiteGlobalSettings.MySiteName.

    Thanks,

    Vijay.

  36. Jaymz on July 8, 2009 11:55 am

    Vijay,

    You would still need to check for null’s in your example, as you’re just throwing the exception, so you’d need to handle that exception at the location you’re accessing the property.

    You’re method would work if instead of throwing it up, you return a valid value. So for strings, instead of returning null, you return String.Empty.

    Depends on your situation and what kind of developers you have I suppose.

  37. Jack on July 9, 2009 4:18 am

    Lots applications and dlls use the application setting, NETOOP is the same and easy to master ;)

  38. Martin on July 9, 2009 5:32 am

    I think you need to do a bit more investigation.

    It does make sense to deal with some items like this, and it’s handled reasonably well, so kudos. However, your assumption that the web.config settings are not cached because they take longer to return is not necessarily valid. As others have pointed out, the MSDN documentation states that they are cached.

    One reason it might take longer to return items via the AppSettings accessor is that it’s using a dictionary rather than a direct reference to a variable.

  39. Joe Stagner on July 9, 2009 8:33 am

    web.config settings ARE cached when NOT runnign in debug mode, but still much slower as per the tests in the otherpots.

  40. Joseph on July 9, 2009 4:25 pm

    Joe,

    Would this be an ideal way to create a reference to an object to be used application wide instead of instantiating it whenever a method is needed? Such as the ProductBLL in the example here: http://www.asp.net/…/tutorial-02-vb.

    Thanks,

    Joseph

  41. Joe Stagner on July 10, 2009 7:14 am

    Hi Joseph,

    It might, but it really depends on your application. I suggest you restrict "global" ojects to those that will be widely and freqently used since they use memory.

    Remember, this object is STATIC (every user doesn’t create a copy.)

  42. Dave Erwin on July 10, 2009 7:54 am

    Thanks for the info. Great post. Just did a variation in a Winforms app to grab the db connection strings from appsettings into a static class. Always wondered how much caching was going on and what the performance impact would be. Haven’t had time to measure it but it made a visible difference.

  43. Anatoliy on July 11, 2009 6:21 am

    Another helpful thing can be to storing settings out of web.config. I’m point settings section to another file and it work with native .NET config accessors and doesn’t cause restarting of application when settings changed. In this case instead of putting list of properties inside web.config we just need to write something like this:

    <appSettings configSource="settings.config"/>

    Extending your class with file FileSystemWatcher will be universal solution even for dynamic data.

Write a Comment

Let me know what you think?