thefrozencoder

Programming and Technology blog

Move your appSettings out of the web.config file

Introduction

This post goes about showing you how you can implement common global settings without using the web.config's appSettings section.  The idea is simple and taken from the latest craze of document based databases like RavenDB.  Why not create an object for your settings serialize it to a standard format and then just persist it to a file.  Now you probably don’t want to go and store passwords and such in the file (unless you encrypt them first) but for the most common settings it’s a nice alternative to the web.config appSettings which is pretty limited.  Now some people may say why not a database?  Well unless you are running under a server farm (and then you probably have a common share between all web servers in the farm) to me a database is a little over-kill for the most part

The code samples in this post can be downloaded using the link at the bottom and were created using Visual Studio 2010.  There are samples for both C# and Visual Basic.NET in the download file as well.  There is an external dependency (JSON.NET) that is included in the lib folder it is used to serialize and de-serialize the SettingsStore object.

Implementation

Default.aspx page UI

The UI is simple enough, just have a way to allow users to update the settings from the setting class.

SettingsLib Code

The SettingsLib class implements the getting and the persisting of the actual settings.  By default the site_settings.config file is stored in a folder called app_data, this can be changed to anything but just remember the windows account that your website runs under must have write access to this folder for the settings to be persisted.

    public static class SettingsLib
    {
        public const string SETTINGS_FILE_NAME = "site_settings.config";

        /// 
        /// Gets the current Settings object from the settings store
        /// 
        /// Settings object
        public static SettingsStore GetSettings()
        {
            return JsonConvert.DeserializeObject(ReadSettingsFile());
        }

        /// 
        /// Saves the settings to the settings store
        /// 
        ///The current Settings object
        /// 
        public static bool SaveSettings(SettingsStore settings)
        {
            return WriteSettingsFile(JsonConvert.SerializeObject(settings));
        }

        /// 
        /// Reads the json data from the settings file
        /// 
        /// json string from the file
        private static string ReadSettingsFile()
        {
            string settings = "{ }";
            string path = GetPath();

            try
            {
                if (File.Exists(path))
                    settings = File.ReadAllText(path);
            }
            catch (Exception) { }

            return settings;
        }

        /// 
        /// Writes the json string to the settings file
        /// 
        ///The json string that represents the Settings object 
        /// True | False if the write was successful
        static bool WriteSettingsFile(string json)
        {
            string path = GetPath();

            try
            {
                File.WriteAllText(path, json);
                return true;
            }
            catch (Exception) { }

            return false;
        }

        /// 
        /// Returns the full file path to the settings file
        /// 
        /// 
        static string GetPath()
        {
            string path = System.Web.HttpContext.Current.Server.MapPath("~\\app_data");

            if (!path.EndsWith("\\")) path += "\\";

            path = string.Concat(path, "\\", SETTINGS_FILE_NAME);

            return path;
        }
    }

SettingsStore Class

The SettingsStore class is just a simple class that implements your settings as an object using properties.  JSON.NET will serialze most primative .net types as well collections too which makes it more flexable than using the web.config file.

    /// 
    /// Class to hold all of your settings
    /// 
    public class SettingsStore
    {
        public string UploadFolder { get; set; }
        public string EmailErrorsTo { get; set; }
        public string EmailServerHostname { get; set; }
    }

Code SettingsStoreSample.zip (176.40 kb)

Installing a 3rd party expansion bay in my laptop

I recently purchased a 3rd party expansion bay caddy (replacement part AK868AA) for my HP EliteBook 8350p laptop so I could have two HD's as well upgrade my original HD to a 7200rpm larger drive.  I would end up installing the new HD as my primary and use the original as a secondary "data" drive for music, videos, VM's and other large files.

I purchased the expansion bay caddy from a 3rd party company (NewmodeUS.com) off of their eBay store and had no problems with the transaction.  Upon receiving the caddy I also noticed that there were no instructions but really how hard can it be right?

Actually I did have one issue when I went to install the caddy into the laptop, it involved a little extra work so I found.  Below is the process I used to install the HD into the caddy and into my laptop.  It does not explain how to remove the original HD and replace it with the new HD.  HP has manuals for that on their site.

The following steps are done at your own risk and I cannot take any responsibility if any damaged is caused by you or to your laptop.  To make things easier my laptop was sitting with the battery compartment facing up or away from me.

Step 1: Remove the battery from the laptop.

Step 2: Remove the original expansion bay caddy (the one that holds the DVD player) by unscrewing the screw that fastens the expansion bay caddy to the laptop chassis and using a flat head screw driver push on the silver tab in the picture to the left to pop the caddy out far enough so you can remove it (see image below as a reference).

Step 3: Prep your new expansion bay caddy by installing your new hard drive, make sure to screw the HD to the caddy and transfer the fastening mounting bracket from the existing caddy to your new caddy using the supplied screws

Step 4: Use 3 screws from the supplied screws and fasten your new expansion bay cover, there are 3 screw holes on the bottom of the expansion bay caddy so that the case stays closed.

Step 5: Slide the expansion bay caddy into the expansion bay is flush with the laptop case or until you feel it cannot go in anymore.  The silver tab you pried to release the caddy should be visible in the slot, if you do not see the little silver tab then you may have to follow steps 6 - 9.

Step 6: Remove the memory cover by unscrewing two screws pictured below and lift and slide the cover to the right.

Step 7: If you have memory in the bay closest to the expansion bay caddy (left memory bay) you might want to remove it by prying the two sliver retainers  on each end of the RAM module away from the center of the RAM module, the RAM module will pop up at an angle so you can remove it.

Step 8: If you look at the picture below you will see the grey connector (circled in red), this is the expansion bays SATA connector (do this by looking inside of the laptop at an angle toward the expansion bay slot).

Step 9: Slide the expansion bay caddy into the slot until it stops.  Slide the flat head screw driver under the chassis so that it rests on the SATA connector then lift up on the screwdriver using the chassis as a leverage point so you can carefully push the SATA connector downwards slightly.  At the same time push the expansion bay caddy in.  The caddy should slide the rest of the way in (it did in my case but your mileage may vary based on the laptop model).  You now should see the little silver tab you had to pry to get the DVD player out.

Step 10: Once this is done screw the fastening screw down and put back all the covers/memory/screws you removed.

Turn on your laptop and hopefully you should see your new drive.

Note: if you were like me and you made the new HD your primary drive and used the original HD as the drive to go in the expansion bay you will need to go into the BIOS and make sure the expansion bay device is NOT the first device to boot from in the list.  If you don't well your old HD will boot.

Note: Because the second drive is not buried in the laptop you will notice the noise when the second drive is being accessed, it is no way louder than the DVD drive when being accessed but you will notice it if you are copying large or a large amount of files to and from it.

Code highlighting integration for BlogEngine.NET 1.5.x

I decided to integrate some code highlighting into my blog rather than taking screen captures of my code and posting those into the blog.  As I found this requires integrating a code inserting plug-in for TinyMCE 3.x to insert code into the editor and format it properly and syntax highlighting extension for the actual posted code.  The two I chose were:

David Pokluda’s Windows Live Writer Source Code Plug-in found here. I simply took the BlogEngine.NET bits from the download and followed the instructions to install it.  This download also included Alex Gorbatchev’s syntax highlighter - v. 2.0.296 – found here.  The idea is there is a BlogEngine.NET extension that writes the SyntaxHighlighter js code to the pages.

And the code inserting plug-in for TinyMCE v3.x I got from Nawaf’s Blog found here.

I had to do some tweaking to get the TinyMCE plug-in to work the way I wanted.  By default the plug-in wraps the code in a HTML textarea along with some attributes (settings) in the class attribute.  I really don’t like that approach (having a textarea in a post and or the TinyMCE editor when editing).  So I ended up changing the plug-in code to output a HTML pre tag and mapping some of the settings from the plug-in to the settings of the syntax highlighter code since Alex Gorbatchev’s code looks for a pre tag anyway.

The changes I made to the plug-in were in the codehighlighting\js\codehighlighting.js file and these are the changes I made:

function Save_Button_onclick() {
    var lang = document.getElementById("ProgrammingLangauges").value;
    var code = WrapCode(lang);
    code = code + document.getElementById("CodeArea").value;
    code = code + "</pre>";
    if (document.getElementById("CodeArea").value == '') 
    {
        tinyMCEPopup.close();
        return false;
    }
    tinyMCEPopup.execCommand('mceInsertContent', false, code);
    tinyMCEPopup.close();
}

function WrapCode(lang) {

    var options = "auto-links: true; first-line: 1; light: false; ruler: false; smart-tabs: true; tab-size: 4;brush: " + lang + ";";
    var html = "";

    if (lang == 'js' || lang == 'jscript' || lang == 'javascript')
        options = options + "html-script: true;";
    else 
        options = options + "html-script: false;";
        
    if (document.getElementById("nogutter").checked == true)
        options = options + "gutter: false;";

    if (document.getElementById("collapse").checked == true)
        options = options + "collapse: true;";

    if (document.getElementById("nocontrols").checked == true)
        options = options + "toolbar: false;";

    html = "<pre class='" + options + "'>";

    return html;
}

function Cancel_Button_onclick() {
    tinyMCEPopup.close();
    return false;
}

As you can see most of the changes were to the WrapCode function (if you compare the original to my version side by side).  Other than that nothing really needed to be done to the syntax highlighter code or the BlogEngine.NET extension.

Instructions for installation can be found on each respective website.

Note: There is a bit of weirdness with the TinyMCE plug-in where if there is HTML tags in your code you will need to manually encode them, I am not sure what is going on but I find it's not that much of a big deal.

Enjoy

No more IE6 BlogEngine.NET Extension

So I decided to update my blog engine to the newest version and along with that I wrote a simple extension to detect IE6 users and redirect them to a non-supported browser page.  Not that my theme cannot handle IE6 but I feel I should get on board and help as much as I can with the movement to rid the internet of this outdated browser.

The extension is pretty simple and uses the built in Response.Browser object which should work for IE6 nicely.  To make an extension for BlogEngine is pretty easy just create a class with a constructor with no parameters and then wire up one or more events that the BlogEngine raises to your event in your extension class.  Below is my extension class for the redirect logic.

using System;
using System.Web;
using BlogEngine.Core;
using BlogEngine.Core.Web;
using BlogEngine.Core.Web.Controls;
using BlogEngine.Core.Web.HttpHandlers;

[Extension("Redirects users with non-supported browsers to an alternate download page", "1.0", "thefrozencoder.ca")]
public class NonSupportedBrowser
{
    public NonSupportedBrowser()
    {
        Post.Serving += new EventHandler(ServingHandler);
        Page.Serving += new EventHandler(ServingHandler);
    }

    void ServingHandler(object sender, ServingEventArgs e)
    {

        HttpContext context = HttpContext.Current;

        if (context != null && !context.Items.Contains("NonSupportedBrowserTest"))
        {
            System.Web.UI.Page page = context.CurrentHandler as System.Web.UI.Page;

            if (page != null)
            {
                context.Items.Add("NonSupportedBrowserTest", 1);

                if (context.Request.Browser.MajorVersion <= 6 && context.Request.Browser.Browser.Equals("IE"))
                {
                    string file = System.Configuration.ConfigurationManager.AppSettings["NonSupportedBrowser"];

                    context.Response.Redirect(file, true);
                }
            }
        }
    }
}

As you can see in the constructor I wire up the Page.Serving and Post.Serving events to my own method.  I create a context item (NonSupportedBrowserTest) and check for it because the event will be called more than once in the lifetime of the request.   I also store the file name in an appSettings key/value so I can change the file to be redirected to (simple HTML file in this case).  All that is required is to place the code file in the App_Code\Extensions folder and add the HTML file with the instructions to download a newer browser.

If you are looking for some ideas for this page I simply used the code from the IE6 No More website.

Windows 7 on my HP EliteBook 8530p

I was able to install Windows 7 Professional (x64) on my Dev laptop today.  It didn’t take that long to install and once up and running I had 6 Unknown Devices present in the Device Manager.  All I had to do for 4 of them was right click on the device and Update Driver from internet.  Windows Update recognized the 4 devices and downloaded drivers for them.  This is a list of the drivers that had to be downloaded or installed manually:

  • Ricoh Memory Stick Host Controller (driver downloaded from windows update)
  • Ricoh SD/MMC Host Controller (driver downloaded from windows update)
  • Ricoh xD-Picture Card Controller (driver downloaded from windows update)
  • AuthenTec Inc. AES2810 (Finger print sensor) (driver downloaded from windows update)
  • HP Drive Guard Driver (download HP 3D Driveguard (Vista) softpaq sp39410.exe)
  • Direct Application Launch Button (download HP Quick Launch Buttons (softpaq sp43616.exe))

Once the drivers where updated manually I noticed that I had 4 new Windows Updates to download all of which were the following drivers:

  • A newer AuthenTec Inc. AES2810 driver
  • A newer ATI Mobility Radeon HD 3650 driver
  • A newer Intel(R) 82567LM Gigabit Network Connection driver
  • A newer Agere Systems HDA Modem driver

All in all a pretty clean and simple install.  That probably more so because the the hardware is fairly new.

The only thing that does not work properly is the mute button (part of the quick launch buttons).  Not a big deal I will probably just have to update the software when HP updates its library for Win7 in October.  Other than I am really liking Win7 so far on this laptop, it runs very well alongside the 8GB of RAM I have installed.

Update: 2009-08-08 - Seems I was wrong about the mute button it does work, however it does not register to Windows that the mute button is enabled so Windows does not display the little red disabled symbol on the speaker icon in the notification area.

Update: 2009-08-29 – I was able to get the AuthenTec Inc. AES2810 finger print reader setup to login to Windows 7 with my fingerprint, it works like a charm.  To do this you will need to download the BETA version of the enrolment software here:

The blog site Three Wise Men has a tutorial on how to actually install, setup and enroll your finger print so you can start using this feature.

Update: 2009-10-22 - HP has started to release updated drivers for the 8530p which the new audio driver has fixed my mute button issue listed above.  As of todays date (2009-10-22) there are no Windows 7 Professional (x64) drivers.  I have installed the Windows Home (x64) drivers and they seem to work as expected.  Visit the HP site here.