Blog

Blogging on programming and life in general.

  • Web browsers have come a long way since the days of Internet Explorer 6 release back in 2001. You would think 9 years on we would have all dumped this piece of software in the garbage heap by now. Alas, we still have users to this very date who still use IE6 either due to personal preference or by force (company IT policies).

    As everyone knows, developing a site to be compliant with main stream browsers in addition to carrying out additional fixes to fit in with the slim 6.7% of global users can be a real pain. So instead of trying to fit your site around the small number of IE6 users, why not just knock some common sense into them and notify them to upgrade.

    Thankfully, there is a really easy and polite way to do this. Go to http://code.google.com/p/ie6-upgrade-warning/ and download the JavaScript file and embed the following code to your webpage…

    <!--[if lte IE 6]>
        <script src="js/ie6/warning.js"></script>
        <script>window.onload=function(){e("js/ie6/")}</script>
    <![endif]-->
    

    …which outputs the following result:

    IE6 Upgrade Warning

    As great as this idea is I don’t see many web developers or web agencies implementing this on the sites they create unless really needed. Nevertheless, its step in the right direction to hopefully put a final nail into that IE6 coffin!

  • I am currently in the process of learning how to build applications for the iPhone. I have recently upgraded from the iPhone SDK 3.0 simulator to the iPhone SDK 4.0 simulator. But this caused some issues when trying to run some of my previous applications I developed prior to when I had the iPhone 3.0 simulator installed.

    Normally, the dropdown box within the XCode window allows you to select different simulators. For example: iPad Simulator 3.2 or iPhone Simulator 4.0. As you can see from my screenshot (below), none of these options were available.

    Base SDK Missing

    Apparently, the iPhone 4.0 SDK can still have the ability to run iPhone 3.0 applications and this is something we should be doing from now on. This requires a couple of changes to carry out in your older 3.0 projects.

    Firstly, you will need to go to Project > Edit Project Settings. When the window appears, click on the Build tab and change the “Base SDK” value to “iPhone Simulator 4.0”.

    Edit Project Settings

    Secondly, go to Project > Edit Active Target. When the window appears, you will have to carry out the same procedure as you carried out in the “Edit Project Settings” whereby you click on the Build tab and change the “Base SDK” value to “iPhone Simulator 4.0”.

    Edit Project Target If you have carried out the changes correctly, you should be able to Build and Run your project successfully. I admit this is not exactly ideal to do this if you have many iPhone 3.0 application projects. But I suppose this fix is better than nothing and plus its quite a quick change.

  • Android Memory I have a HTC Hero which was recently upgraded from Android 1.5 to 2.1 a few months back. It has definitely been a significant and worthwhile upgrade packing in lots of new extra features and most importantly extra applications to download from the Android Market.

    The only downside to the upgrade is that I now have less memory to play with and this can cause a detrimental effect if you get the “Phone memory is running low” warning. Since I received this warning I found that all my Google Synchronisation tasks stopped syncing automatically. Even if I tried manually starting the synchronisation service nothing would happen. In addition, I couldn’t even download any applications from the Android Market.

    Soon as I went on a massive clear out on my phone and resolved the low memory error, my Google Synchronisation worked instantaneously. All the problems I previously had were magically rectified. Its just a shame that all the applications get stored onto the phone memory rather than the external memory.

    The weirdest thing is that I still had around 14MB of free space on my phone prior to having my cleanup. I find it a little strange the low memory threshold is set so high.

    I guess its good to know that Google has rectified this issue by allowing applications to be stored on external memory in their Android 2.2 release. Unfortunately, it highly unlikely my HTC Hero will see this update.

  • Over the last week or so, I have had the most frustrating time creating a Mac OS X Snow Leopard environment using VMware. I won’t go into the whole process I went through to create my Virtual Machine. There are many online articles for you to Google (or Bing :-P) that show you the step-by-step procedures on how to create a Mac OS virtual environment.

    All I can say it took a lot of blood, sweat and tears! You may find that you need to cross-reference between a few sites in order to get the winning combination for a working VMware environment.

    Anyway, if you are one of the lucky ones to have successfully built a Snow Leopard environment, you may have come across an issue whereby your VMware environment randomly freezes for no apparent reason. Now this is quite annoying. After much searching and constant VMware configuration changes, I could not get to the bottom of the issue. I knew that it could not have been to do with the setup, after all I had a fully functioning Mac environment.

    What I noticed is that my environment would never freeze whilst I was using it. It only froze if I left it idle for long periods of time. You are now probably thinking:

    GET TO THE POINT! HOW DID YOU FIX IT???

    Well the cause of the environment to freeze is due to the Energy Saver settings found under System Preferences in your Mac OS (Apple icon > System Preferences > Energy Saver). You will find that it is default to 15 minutes idle time before going into sleep mode. All you need to do is set both Computer Sleep and Display Sleep to Never. As a precaution I also unticked the “Put the hard disk(s) to sleep when possible"

    MacOSEnergySaver

  • In SharePoint 2003, you will notice when you change the name of a site, the change is not reflected in the intranet URL. Modifying the site name within “Site Settings” will only change the title that is displayed when you visit the site.

    You have two options to change the site name you see in the URL:

    1. Delete and recreate your site.
    2. Backup your current site and restore content elsewhere on the intranet.

    You really wouldn’t want to consider the first option if your SharePoint site currently stores high volume of information. The best option would be to carry out a backup and restore using SharePoint’s “stsadm” command prompt. The time it takes to run the backup and restore process will entirely depend on the size of your site.

    So here’s the scenario. We have an intranet that currently contains a site called “InsuranceClaims”. However, this site needs to add additional data relating to employee health schemes. The site name in the web address needs to be renamed to “InsuranceAndHealthClaims”. In order to make this change, the following needs to be carried out:

    1. Backup the “InsuranceClaims” site using the stsadm backup command. The site has been backed up to a file called insurancebackup.bak.
    stsadm.exe -o backup -url http://intranet.computing-studio.com/sites/insuranceclaims -filename C:\insurancebackup.bak
    
    1. Create a new site called “InsuranceAndHealthClaims” from the SharePoint intranet.
    2. Restore the contents of the backup to the new site using the stsadm restore command.
    stsadm.exe -o restore -url http://intranet.computing-studio.com/sites/insuranceandhealthclaims -filename C:\insurancebackup.bak
    

    Providing all goes well when you run the backup and restore stsadm commands, you should get a “Operation completed successfully” message.

  • Over the last few months I have had the ability to mess around with a bit of jQuery. Even though I don’t have the complete understanding on how it works, I can see the benefits of writing my code in jQuery compared to bashing out lots of lines of JavaScript to do the same thing.

    One the cool features I have used is calling one of my .NET methods using the “$.ajax” jQuery command. In my example (below), I have created two aspx pages. The code-behind of my first page  (jQueryMethodTest.aspx) will only contain a public static method called “WhatIsYourName”, which returns a string value.

    [WebMethod]
    public static string WhatIsYourName(string name)
    {
        if (!String.IsNullOrEmpty(name))
        {
            return String.Concat("Hello ", name, "!");
        }
        else
        {
            return String.Empty;
        }
    }
    

    Remember, the jQueryMethodTest.aspx page only needs to contain our method nothing else! Additional methods can be added. Just don’t add any web controls.

    The second page (jQueryAjax.aspx), will contain our jQuery code and some HTML to output our result from calling the “WhatIsYourName” method.

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <script type="text/javascript" language="javascript" src="javascript/jquery.js"></script>
    </head>
    <script type="text/javascript">
        $(document).ready(function() {
            $("#btnSubmitName").click(function(event) {
                $.ajax({
                    type: "POST",
                    url: "jQueryMethodTest.aspx/WhatIsYourName",
                    data: "{'name': '" + $('#name').val() + "'}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function(message) {
                        ShowPopup(message);
                    },
                    error: NameFailed
                });
            });
        });
    
        function ShowPopup(result) {
            if (result.d != "") {
                $("#Message").html(result.d);
            }
            else {
                $("#Message").html("I didn't get your name.");
            }
        }
    
        function NameFailed(result) {
            $("#Message").html(result.status + ' ' + result.statusText);
        }  
      </script>  
    
    <body>
        <form id="form1" runat="server">
        <div>
            <input id="name" name="name" type="text" />
            <br />
            <input id="btnSubmitName" name="btnSubmitName" type="button" value="Submit" />
            <br /><br />
            <span id="Message" style="color:Red;"></span>
        </div>
        </form>
    </body>
    </html>
    

    If all goes well, you should get the following result:

    Calling ASP Method Using jQuery

    The “$.ajax” jQuery command requires the following parameters in order to work:

    • url – links to where our .NET method is placed.
    • data – retrieves the value from some control in our page to pass to our method. Remember, the name of the parameter must be named the same as the parameter from our .NET method.
    • dataType – the response type.
    • contentType – the request content type.
    • success – the JavaScript function that gets fired on postback.
    • error – the Javascript function that gets fired if there is a failure. This is an optional parameter.

    I guess jQuery’s motto really is true: “write less, do more”.

  • UPDATE queries are great to modify all information stored within our column. But what if we needed to only update a specific phrase or word within our column?

    Well, we can use an UPDATE query along with a REPLACE function. It can be used like this:

    UPDATE <table_name>
    SET <column_name> = Replace(<column_name>, 'old phrase', 'new phrase')
    
  • I needed to create a custom web part using Visual Studio 2003 for a SharePoint 2003 client intranet, something I have never done before. As fellow SharePoint developers will know, you need to strongly name your project assembly whenever you need deploy a custom made web part.

    Visual Studio 2005 and onwards allows you to easily create a strongly named key through the graphical user interface. In Visual Studio 2003, you will need to use the Visual Studio 2003 Command Prompt. You can find the Visual Studio 2003 Command Prompt by going to: Start > Program Files > Visual Studio 2003 > Visual Studio.NET Tools > Visual Studio .NET 2003 Command Prompt.

    Visual Studio 2003 Command Prompt

    Once the command prompt window has opened all you need to do is enter the following to create a SNK:

    Setting environment for using Microsoft Visual Studio .NET 2003 tools.
    (If you have another version of Visual Studio or Visual C++ installed and wish
    to use its tools from the command line, run vcvars32.bat for that version.)
     
    C:\Documents and Settings\Administrator\Desktop>sn -k MyKey.snk
     
    Microsoft (R) .NET Framework Strong Name Utility  Version 1.1.4322.573
    Copyright (C) Microsoft Corporation 1998-2002. All rights reserved. 
     
    Key pair written to MyKey.snk
     
    C:\Documents and Settings\Administrator\Desktop>
    

    As you can see from my command prompt example above, I am creating a new SNK file called MyKey.snk. This SNK file will be generated on my Desktop.

  • I had created some .NET UserControl’s that I needed to dynamically add to a Panel control within my page. I previously thought generating my UserControl’s dynamically would be the same as dynamically generating any other .NET Control, like this:

    private void CreateControls()
    {
        //Create control
        TextBox txtUser = new TextBox();
        txtUser.ID = "txtUser";
        txtUser.Text = "Please enter a value";
     
        //Add Control to Panel already in our .NET page
        pnlControlPlaceHolder.Controls.Add(txtUser);
    }
    

    But I was wrong! :-)

    Fortunately, there is a really easy way to to add a UserControl dynamically by simply making use of the “LoadControl” method. The “LoadControl” method takes a single parameter containing the virtual path of your UserControl. For example:

    private void CreateControls()
    {
        //Create control
        Control myUserControl = LoadControl("MyUserControl.ascx") as MyUserControl;
        myUserControl.ID = "ucMyControl";
     
        //Add Control to Panel already in our .NET page
        pnlControlPlaceHolder.Controls.Add(myUserControl);
    }
    

    Easy!

  • As promised, I have been busy creating a custom web part to display Microsoft Charts within my SharePoint reporting dashboard. Before you even think of wanting to use Microsoft Chart in a SharePoint environment, there are a few boring tasks you need to carry out beforehand:

    Step 1: Copy Charting Files To SharePoint

    1. Download Microsoft Chart here.
    2. Ensure the System.Web.DataVisualization.dll is in the GAC of your SharePoint server. If not, go to your Microsoft Chart installation directory (C:\Program Files\Microsoft Chart Controls\Assemblies). You will find all the dll’s here.
    3. Copy the charting images from the MS Chart project directory.

    Image Directory 4. On your SharePoint server, go to the 12 hive and create a new folder called “MicrosoftChartControls” in the Images directory.

    SharePoint Image Directory

    Step 2: Modify SharePoint’s Web.Config File

    1. Add “System.Web.DataVisualization” to the SafeControls section.
    <SafeControls>
        ...
        ... 
        <SafeControl Assembly="System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"  Namespace="System.Web.UI.DataVisualization.Charting" TypeName="*" Safe="True" AllowRemoteDesigner="True"/>
    </SafeControls>
    
    1. Add the “ChartImg.axd” path to httpHandlers section.
    <httpHandlers>
        ...
        ...
        <add verb="*" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
    </httpHandlers>
    
    1. Add a new AppSetting after the </system.workflow.componentmodel.workflowcompiler> tag. As you can see, this AppSetting contains the URL to where our charting images are stored.
    </System.Workflow.ComponentModel.WorkflowCompiler>
    <appSettings>
        <add key="ChartImageHandler" value="storage=memory;timeout=20;URL=/_layouts/Images/MicrosoftChartControls/" />
    </appSettings>
    
    1. Lastly, ensure you add your own custom web part charting control to the SafeControls section as I have done.
    <SafeControl Assembly="MOSSCharts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d463a6b3aa294272" Namespace="MOSSCharts" TypeName="*" Safe="True" AllowRemoteDesigner="True" />
    

    If you still have problems with SharePoint failing to recognise the charting API, view this MSDN Forum posting.

    My Custom Chart Example – Bar Chart

    I decided it would be more useful to create a charting web part that would display graphical data from a database, instead of using randomised or hard coded values. My charting web part contains the following properties:

    • Chart Title
    • Database Connection String – in the real world you wouldn’t include this property. But it just makes it so much more easier to change database connection strings.
    • Series 1 Query – will contain a SQL Query based on the results you want returned.
    • Series 1 X Data – the column data you want displayed in the Bar Chart X Axis.
    • Series 1 Y Data - the column data you want displayed in the Bar Chart Y Axis.

    Chart Properties

    Based on the properties above, your chart will look something like this:

    Custom Chart

    This is how you can create the Bar Chart web part:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.DataVisualization.Charting;
    using System.Drawing;
    using System.Data;
    using System.Data.Sql;
    using Microsoft.SharePoint;
    using System.Web.UI.WebControls.WebParts;
    using System.Data.SqlClient;
    using System.ComponentModel;
    using Microsoft.SharePoint.WebPartPages;
    using System.Web.UI.WebControls;
     
    namespace MOSSCharts
    {
        public class BarChart : Microsoft.SharePoint.WebPartPages.WebPart
        {
            private string chartName;
            [WebBrowsable(true), Personalizable(true)]
            [Category("Chart Details")]
            [FriendlyName("Chart Title")]
            public string ChartName
            {
                get { return chartName; }
                set { chartName = value; }
            }
     
            private string connectionString;
            [WebBrowsable(true), Personalizable(true)]
            [Category("Database Details")]
            public string ConnectionString
            {
                get { return connectionString; }
                set { connectionString = value; }
            }
     
            private string querySeries1;
            [WebBrowsable(true), Personalizable(true)]
            [Category("Series 1 Data")]
            [FriendlyName("Series 1 Query")]
            public string QuerySeries1
            {
                get { return querySeries1; }
                set { querySeries1 = value; }
            }
     
            private string xColumnDataSeries1;
            [WebBrowsable(true), Personalizable(true)]
            [Category("Series 1 Data")]
            [FriendlyName("Series 1 X Data")]
            public string XColumnDataSeries1
            {
                get { return xColumnDataSeries1; }
                set { xColumnDataSeries1 = value; }
            }
     
            private string yColumnDataSeries1;
            [WebBrowsable(true), Personalizable(true)]
            [Category("Series 1 Data")]
            [FriendlyName("Series 1 Y Data")]
            public string YColumnDataSeries1
            {
                get { return yColumnDataSeries1; }
                set { yColumnDataSeries1 = value; }
            }
     
            protected override void CreateChildControls()
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    try
                    {
                        //**************************************************************
                        //Create Connection String
                        //**************************************************************
                        SqlConnection sqlConn = new SqlConnection(ConnectionString);
     
                        //**************************************************************
                        // Create Chart Control
                        //**************************************************************
                        Chart barChart = new Chart();
                        barChart.Width = 412;
                        barChart.Height = 296;
     
                        //Specify palatte to use
                        barChart.Palette = ChartColorPalette.BrightPastel;
     
                        if (!String.IsNullOrEmpty(ChartName))
                        {
                            Title t = new Title(ChartName, Docking.Top, new System.Drawing.Font("Trebuchet MS", 14, System.Drawing.FontStyle.Bold), System.Drawing.Color.FromArgb(26, 59, 105));
                            barChart.Titles.Add(t);
                        }
     
                        //Create chart area
                        barChart.ChartAreas.Add("ChartArea1");
     
                        // Show as 3D
                        barChart.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;
     
                        // Show columns as clustered
                        barChart.ChartAreas["ChartArea1"].Area3DStyle.IsClustered = false;
     
                        // Show X axis end labels
                        barChart.ChartAreas["ChartArea1"].AxisX.LabelStyle.IsEndLabelVisible = true;
     
                        // Set rotation angles
                        barChart.ChartAreas["ChartArea1"].Area3DStyle.Inclination = 15;
                        barChart.ChartAreas["ChartArea1"].Area3DStyle.Rotation = 20;
                         
                        //**************************************************************
                        // Add series data to chart 
                        //**************************************************************
     
                        //Create Series 1 if there is data
                        if (!String.IsNullOrEmpty(XColumnDataSeries1) && !String.IsNullOrEmpty(YColumnDataSeries1) && !String.IsNullOrEmpty(QuerySeries1))
                        {
                            //Add a new series
                            barChart.Series.Add("Series1");
     
                            // Set series chart type
                            barChart.Series["Series1"].ChartType = SeriesChartType.Column;
     
                            // Draw as 3D Cylinder
                            barChart.Series["Series1"]["DrawingStyle"] = "Cylinder";
     
                            barChart.Series["Series1"].BorderColor = Color.FromArgb(26, 59, 105);
                            barChart.Series["Series1"].Color = Color.CornflowerBlue;
                            barChart.Series["Series1"].BackSecondaryColor = Color.Navy;
                            barChart.Series["Series1"].BackGradientStyle = GradientStyle.DiagonalLeft;
    
                            barChart.Series["Series1"]["PointWidth"] = "0.8";
     
                            SqlCommand sqlCmdSeries1 = new SqlCommand(QuerySeries1, sqlConn);
     
                            barChart.DataSource = sqlCmdSeries1;
     
                            barChart.Series["Series1"].XValueMember = XColumnDataSeries1;
                            barChart.Series["Series1"].YValueMembers = YColumnDataSeries1;
    
                        }
     
                        barChart.DataBind();
     
                        Controls.Add(barChart);
                    }
                    catch (Exception ex)
                    {
                        Label lblError = new Label();
                        lblError.Text = "An error has occurred. Please ensure you have entered correct chart details";
     
                        Controls.Add(lblError);
                    }
                });
            }
        }
    }
    

    The code (above) provides a basis to display a database driven chart within SharePoint. With some further tweaks, your Reporting Dashboard could look something like this:

    SharePoint Report Dashboard

    If you would like the code for some of my other charts displayed within my Reporting Dashboard, please leave a comment.