Blog

Blogging on programming and life in general.

  • Kentico LogoFor many years, I've been a happy BlogEngine user. However, recently my website was starting to expand in a way that wasn't flexible enough for the BlogEngine platform. Don't get me wrong, BlogEngine is a great blogging platform and it is without a doubt one of the best out on the market. But the capabilities and features Kentico provides made moving over to another platform an easy decision.

    The future of my site needed something that would give me free reign and control on making full customisations myself in a solid framework, and Kentico seemed to fit this requirement.

    Having worked with the Kentico platform for quite a few years now, I was impressed by how easy or complex I could make a site. Most importantly, the page perfomance of my site has got quite a boost. For a site that doesn't look like is doing much at face value, it is behind the scenes.

    What was the migration process like?

    Migrating all my BlogEngine content into Kentico did take some time, but the Kentico Import tool really does take the hassle out of getting key blog post information into the CMS. Just don't be expect tags and categories to be imported in the process. Migrating these facets is a manual job.

    In addition, I decided to overhaul the friendly URL's used for my blog posts in keeping with the URL structure provided by BlogEngine. Even to this day, I'm not sold on the way Kentico generates it's friendly URL's for blog posts. For example:

    /Blog/February-2013/My-Blog-Post.aspx
    

    When it should be the following format:

    /Blog/2013/02/03/My-Blog-Post.aspx
    

    Luckily, it was pretty easy to write a Custom Eventhandler to add additional custom URL paths whenever I update or insert a new post (will add a post in the near future on how to do this).

    I still have some additional features to add to this site (and dare I say fixes!) so watch this space...

  • I noticed something very strange whilst working on one of my recent Kentico projects, where I required a query string value to be case-sensitive. You might be asking why? Well the plan was to pass case-sensitive Base64 random value in a bit.ly ID format. For example: www.mysite.com/Home/iAfcTy.

    So I added a Wildcard URL to one of my pages to keep the URL looking nice and tidy. In this case: “/Home/{ID}”.

    Kentico Document Url Path

    Something with the most simplest of intensions ended up being a bit of a nightmare and to demonstrate what I experienced, see the following test-cases using Kentico’s Wildcard parameter.

    Test 1

    Passing “Hello” to the query string parameter resulted in the following:

    Kentico Wildcard Case 1

    This is the correct outcome.

    Test 2 – Things get interesting!

    Passing “HELLO” to the same query string parameter resulted in the following:

    Kentico Wildcard Case 2

    As you can see, the query string has been cached and resulted in the same value being used. It seems Kentico completely disregards the case sensitivity and it’s only by adding or removing characters that Kentico detects the value passed has changed.

    ***

    My understanding is that by default Kentico accepts the URL’s as entered by the website user. I thought by going to CMS Site Manager and changing the URL settings to “Use exactly the URL of the document” would accept case-sensitive lettering .

    Kentico Redirect Valid Urls

    As it turns out through my testing, this setting under “URL's and SEO” section doesn’t fix the issue and this may only work for document page names and not the query strings values themselves.

    For one moment, I thought I managed to find a bug in the Kentico platform and was hoping that I'd get a tree planted bearing my name through Kentico’s brilliant tree for a bug campaign. Alas, this was not the case. After discussing in great detail the problem with emails sent back and forth I couldn't seem to get the support personnel to replicate the issue.

    But if I'm experiencing this issue across different networks, workstations and installations, there must be an underlying problem within the Kentico platform.

    If one of my fellow Kentico experts can can try what I have stated in my post and report their findings in the comments section, it would be much appreciated.

    Who knows, there might be a really simple thing I’ve overlooked.

    Workaround

    Using the standard way of passing a query string value works perfectly and it only seems Kentico Wildcard URL’s  experiences this issue. So instead of using the Wildcard method, you will have to pass values in the following format:

    www.mysite.com/Home/?ID=Hello
    
  • I’ve been working on a PowerShell script that required to be automatically run every 5 minutes. As you probably guessed, using Windows Task Scheduler is the way to go.

    Prior to assigning any scripts or programs to a scheduled task, I always run them manually first to ensure all issues are rectified.  We all know if there is an issue whilst running within Task Scheduler, Windows likes to help us by showing us some ambiguous error/success codes.

    Luckily, MSDN provides a comprehensive list of these codes that can be found here: http://msdn.microsoft.com/en-us/library/aa383604

    But there more common codes are listed below:

    0 or 0x0: The operation completed successfully.
    1 or 0x1: Incorrect function called or unknown function called.
    2 or 0x2: File not found.
    10 or 0xa: The environment is incorrect.
    0x41300: Task is ready to run at its next scheduled time.
    0x41301: Task is currently running.
    0x41302: Task is disabled.
    0x41303: Task has not yet run.
    0x41304: There are no more runs scheduled for this task.
    0x41306: Task is terminated.
    0x8004131F: An instance of this task is already running.
    0x800704DD: The service is not available (is 'Run only when an user is logged on' checked?)
    0xC000013A: The application terminated as a result of a CTRL+C.
    0xC06D007E: Unknown software exception.
    
  • Sometimes optimising images to have an adequate image to file size ratio can be difficult when dynamically generating images using “System.Drawing”.

    Over the years, I have worked on quite a few different projects around the use of “System.Drawing” and recently I found a flexible way of being able to have control over the image quality and file size.

    Here’s a snippet of of code from my Generic Handler (.ashx) file:

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "image/jpeg";
    
        //Create a new Bitmap
        Bitmap oBitmap = new Bitmap(800, 800, PixelFormat.Format24bppRgb);
    
        //Load Background Graphic from Image
        Graphics oGraphics = Graphics.FromImage(oBitmap);
    
        #region Your Image Code
         
        //Insert your code here.
    
        #endregion
    
        #region Stage 1: Image Quality Options
        
        oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        oGraphics.SmoothingMode = SmoothingMode.HighQuality;
        oGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
        oGraphics.CompositingQuality = CompositingQuality.HighQuality;
        
        #endregion
    
        //Clear graphic resources
        oGraphics.Dispose();
    
        #region Stage 2: Image Quality Options
    
        //Output image
        ImageCodecInfo[] Info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
        EncoderParameters Params = new System.Drawing.Imaging.EncoderParameters(1);
        Params.Param[0] = new EncoderParameter(Encoder.Quality, 100L); //Set image quality
        context.Response.ContentType = Info[1].MimeType;
        oBitmap.Save(context.Response.OutputStream, Info[1], Params);
    
        #endregion
    }
    

    System.Drawing.Graphics Optimisations

    In all my “System.Drawing” development projects, I’ve always set the graphic object quality options (lines 19-22) and found that it never really worked for me. The reason for this is because I always placed these settings after creating my System.Drawing.Graphics object prior to my custom code. So the image was getting optimised before any of my functionality had taken place. Rubbish!

    The key is to set all your System.Drawing.Graphics object settings just before you dispose of it. Makes sense doesn’t it? Don’t know how I made such a noob mistake.

    By default, .NET uses the web safe options when converting Bitmap to an image and setting those four properties will have a big affect on how your image looks.

    Compression Level

    This is the good bit!

    .NET gives you the ability to carry out further tweaks on how your image will be rendered by allowing us to set the compression level. The compression level can be tweaked by modifying the value passed to the “EncoderParameter” constructor (line: 34).

    For another example of how this can be used, take a look at the following MSDN article: http://msdn.microsoft.com/en-us/library/bb882583.aspx

  • Ok I’ll admit Part 2 to my “Beginner’s Guide To Using Google Plus .NET API” has been on the back-burner for some time (or maybe it’s because I completely forgot). After getting quite a few email recently on the subject, I thought now would be the best time to continue with Part 2.

    It’s recommended you take a gander at Part 1 before proceeding to this post.

    As the title suggests, I will be showing how to output user’s publicly view posts. The final output of what my code will produce can be seen on my homepage under the “Google+ Posts” section.

    Create Class Object

    We will create a class called “GooglePlusPost" to allow us to easily store each item of post data within a Generic List.

    public class GooglePlusPost
    {
        public string Title { get; set; }
        public string Text { get; set; }
        public string PostType { get; set; }
        public string Url { get; set; }
    }
    

     

    Let’s Get The Posts!

    I have created a method called “GetPosts” that accepts a parameter to select the number of posts of your choice.

    public class GooglePlus
    {
        private static string ProfileID = ConfigurationManager.AppSettings["googleplus.profileid"].ToString();
        
        public static List<GooglePlusPost> GetPosts(int max)
        {
            try
            {
                var service = new PlusService();
                service.Key = GoogleKey;
                var profile = service.People.Get(ProfileID).Fetch();
    
                var posts = service.Activities.List(ProfileID, ActivitiesResource.Collection.Public);
                posts.MaxResults = max;
    
                List<GooglePlusPost> postList = new List<GooglePlusPost>();
    
                foreach (Activity a in posts.Fetch().Items)
                {
                    GooglePlusPost gp = new GooglePlusPost();
    
                    //If the post contains your own text, use this otherwise look for
                    //text contained in the post attachment.
                    if (!String.IsNullOrEmpty(a.Title))
                    {
                        gp.Title = a.Title;
                    }
                    else
                    {
                        //Check if post contains an attachment
                        if (a.Object.Attachments != null)
                        {
                            gp.Title = a.Object.Attachments[0].DisplayName;
                        }
                    }
    
                    gp.PostType = a.Object.ObjectType; //Type of post
                    gp.Text = a.Verb;
                    gp.Url = a.Url; //Post URL
    
                    postList.Add(gp);
                }
    
                return postList;
            }
            catch
            {
                return new List<GooglePlusPost>();
            }
        }
    }
    

    By default, I have ensured that my own post comment takes precedence over the contents of the attachment (see lines 24-35). If I decided to just share an attachment without a comment, the display text from the attachment will be used instead.

    There are quite a few facets of information an attachment contains and this only becomes apparent when you add a breakpoint and debug line 33. For example, if the attachment had an object of type “video”, you will get a wealth of information to embed a YouTube video along with its thumbnails and description.

    Attachment Debug View

    So there is room to make your Google+ feed much more intelligent. You just have to make sure you cater for every event to ensure your feed displays something useful without breaking. I’m in the process myself of displaying redoing my own Google+ feed to allow full access to content directly from my site.

    Recommendation

    It is recommended that you cache your collection of posts so you are not making constantly making request to Google+. You don’t want to exceed your daily request limit now do you.

    I’ve set my cache duration to refresh every three hours.

  • You have to see it to believe it. The inner geek in me want to purchase this.

    Floppy Disk Coffee Table

    The guys who made this have managed to put in an impressive amount of detail (as much detail as you can get from a floppy disk!).

    Floppy Disk’s were well-known for their lack of storage space, thankfully, there’s a adequate sized secret compartment that is revealed by simply moving the metal shutter.

    More images of this beauty can be seen over at Design Boom: http://www.designboom.com/design/floppy-disk-table-by-axel-van-exel-marian-neulant/

    And whoever said the Floppy Disk is dead!? Smile

  • Touchscreen LaptopI had the opportunity to try out one of my friends new gadget purchases (someone's been a good boy this year!) - the Asus Transformer Infinity. I read a lot about the Asus Transformer range ever since its first release in 2011, but got the impression that this was just another worthless mishmash of tech with a mistaken identity. I never understood why anyone would buy a touchscreen tablet that had a keyboard. That just defeats the whole point of having a tablet device does it not? How wrong was I...

    The combination of a keyboard and touchscreen just works and feels perfectly natural. I always had the misconception that a mouse is needed to accurately communicate with an OS user interface. The more I used the Asus Transformer, the more I wished I had one and oddly when returning back to my Alienware m11x I felt something missing. In my eyes, the good ol' touchpad just seemed inadequate. In all honest, the Asus Transformer touchpad is just as inadequate and a little flaky (possibility due to lack of support by Android). They should have left that out.

    With the advent of next generation on laptop/touchscreen hybrids such as the Microsoft Surface and Lenovo Yoga (which has an awesome ad), maybe there is method in this concept after all and I look forward to using future variations.

    For the moment, all I know for sure is I want a Asus Transformer Infinity!

  • During the latter-end of 2010, Twitter overhauled their somewhat simplistic website to compete with client-side offerings (e.g. TweetDeck, Seesmic). What I found really impressive was a hidden bit of functionality that allowed the user to navigate around the site using keyboard shortcuts (or hot keys). If you haven't tried it, take a look at the list of shortcuts below and try them out.

    Twitter Keyboard Shortcuts

    Some people I know in the industry think it's a pointless feature. But I believe something so simple automatically enhances the users experience when accessing a site. In fact, you could think of hotkeys as an additional web accessibility requirement for those who don’t have a mouse or just prefer the more direct approach in navigating through a site. Many sites have been utilising hotkeys to get their sites to act like locally installed software programmes, for example Google Docs.

    I was very keen on replicating hotkey functionality on my next project. Not surprising, there are a lot of custom jQuery plugins that allowed you to implement some basic keyboard shortcut functionality. The best one I found through trial and error is Mousetrap. I found Mousetrap to be the most flexible plugin to fire your own custom JavaScript events by binding a single, sequence or combination key press.

    Using Mousetrap, I could replicate a simple Twitter-style shortcut to take a user back to the homepage by pressing the following keys in sequence: “G H”:

    Mousetrap.bind("g h",
        function () { 
            window.location = "/Home.aspx"; 
        }
    );
    
  • Published on
    -
    1 min read

    It’ll Be A Sad Day When iGoogle Is No More

    Amongst the number of services Google provides, iGoogle portal has to be at the top of my list. It’s my one stop shop for daily news, weather forecasts and playing the odd game. I was surprised when Google announced they will discontinue the service from November 2013. I was reminded by the deadline on my iGoogle page today, reinforcing that this is going to happen. I was hoping Google would reconsider but it doesn’t look like that's going to happen.

    iGoogle Discontinued

    Google’s decision to discontinue iGoogle in my opinion is a little rash. They claim: “With modern apps that run on platforms likeChromeandAndroid, the need for something like iGoogle has eroded over time”. And this is where the problem lies. Why does everything nowadays have to evolve around an app? Some things are best left accessible through a browser.

    I like getting to work in the mornings and gazing over the days topics. It’s bloody informative! I’ve yet to find an app that matches what iGoogle offers. iGoogle is a one page where everything is displayed without having to click to another page. Google Chrome's substitutes require me to do exactly that. Big waste of time.

    I’m not the type of person to be concerned about change and in most cases I welcome it with open arms. But this will take a little time to get use to.

    Goodbye old friend, you’ll be sorely missed!

  • Safari iOS6It wasn’t until today I found that the Safari browser used on iPad and iPhone caches page functionality to such an extent that it stops the intended functionality. So much so, it affects the user experience. I think Apple has gone a step too far in making their browser uber efficient to minimise page loading times.

    We can accept browsers will cache style-sheets and client side scripts. But I never expected Safari to go as far as caching responses from web services. This is a big issue. So something as simple as the following will have issues in Safari:

    // JavaScript function calling web service
    function GetCustomerName(id)
    {
        var name = "";
    
        $.ajax({
            type: "POST",
            url: "/Internal/ShopService.asmx/GetCustomerName",
            data: "{ 'id' : '" + id + "' }",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            cache: false,
            success: function (result) {
                var data = result.d;
                name = data;
            },
            error: function () {
            },
            complete: function () {
            }
        });
        
        return name;
    }
    
    //ASP.NET Web Service method
    [WebMethod]
    public string GetCustomerName(int id)
    {
       return CustomerHelper.GetFullName(id);
    }
    

    In the past to ensure my jQuery AJAX requests were not cached, the “cache: false” option within the AJAX call normally sufficed. Not if you’re making POST web service requests. It’s only until recently I found using “cache:false” option will not have an affect on POST requests, as stated on jQuery API:

    Pages fetched with POST are never cached, so the cache and ifModified options in jQuery.ajaxSetup() have no effect on these requests.

    In addition to trying to fix the problem by using the jQuery AJAX cache option, I implemented practical techniques covered by the tutorial: How to stop caching with jQuery and JavaScript.

    Luckily, I found an informative StackOverflow post by someone who experienced the exact same issue a few days ago. It looks like the exact same caching bug is still prevalent in Apple’s newest operating system, iOS6*. Well you didn’t expect Apple to fix important problems like these now would you (referring to Map’s fiasco!). The StackOverflow poster found a suitable workaround by passing a timestamp to the web service method being called, as so (modifying code above):

    // JavaScript function calling web service with time stamp addition
    function GetCustomerName(id)
    {
        var timestamp = new Date();
    
        var name = "";
    
        $.ajax({
            type: "POST",
            url: "/Internal/ShopService.asmx/GetCustomerName",
            data: "{ 'id' : '" + id + "', 'timestamp' : '" + timestamp.getTime() + "' }", //Timestamp parameter added.
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            cache: false,
            success: function (result) {
                var data = result.d;
                name = data;
            },
            error: function () {
            },
            complete: function () {
            }
        });
        
        return name;
    }
    
    //ASP.NET Web Service method with time stamp parameter
    [WebMethod]
    public string GetCustomerName(int id, string timestamp)
    {
        string iOSTime = timestamp;
        return CustomerHelper.GetFullName(id);
    }
    

    The timestamp parameter doesn’t need to do anything once passed to web service. This will ensure every call to the web service will never be cached.

    *UPDATE: After further testing it looks like only iOS6 contains the AJAX caching bug.