Blog

Blogging on programming and life in general.

  • ReactJSI've been meddling around with ReactJS over the last week or so, seeing if this is something viable to use for future client projects. I am always constantly on the lookout to whether there are better alternatives on how my fellow developers and I develop our sites.

    Throughout the sample applications I've been building, I constantly asked myself one question: Why Would I Use ReactJS In My Day To Day Development? I am ASP.NET developer who build websites either using Web Forms or MVC Razor. So I am finding it difficult to comprehend whether using ReactJS is viable in these frameworks, especially MVC.

    ReactJS is primarily a view framework where you have the ability to write component-based web applications directly into your JavaScript that then gets output to the DOM virtually - making for a very fast and responsive webpage. It's a different approach to developing websites that I quite like. But for the moment, I just don't see how it can benefit me when the full MVC framework does a pretty good job with all the bells and whistles.

    For example, I segregate all my key HTML markup into partial views in order to increase re-use throughout my web application, which works really well when making AJAX calls where the markup needs to be displayed on the page asynchronously as well as server-side. I can just see by implementing ReactJS, I will be duplicating this process at JavaScript and CSHTML level if a markup change ever needed to be made. If partial views does the job effectively, I'm not too sure the need for ReactJS in my future ASP.NET MVC creations.

    Don't get me wrong - I really like ReactJS. It makes writing JavaScript an even more enjoyable experience purely due to the JSX syntax. Long gone are the days where you have to concatenate strings to form HTML. More importantly, it's readable and truly scalable.

    Unfortunately, it doesn't look like ReactJS is a viable option for me at this moment in time. I can see how it would be a very useful framework for building web applications where there is a requirement for the view to be created strictly client-side along with heavy use of AJAX calls from an API layer to serve data to your application. But in situations where you have two frameworks that provide the ability to create views, in this case ReactJS and ASP.NET MVC, it doesn't make sense.

    I could be talking absolute nonsense and missing the whole point. If this is the case (most likely!), please leave a comment.

  • I decided it was time for my trusted Nexus 5 and I to part ways. We had many good times over the last few years we had known each other. But as things sometimes unfortunately turn out, our time together finally came to an end. The battery life was starting to wane and I really need a phone with a larger capacity - more than 16GB.

    Enough with the sentimentality...

    I am now the proud owner of a Nexus 6P.

    My Nexus 6P

    And what a beauty she is!

    In getting the Nexus 6P, I am about to sell my dear Nexus 5 on eBay, so that it may grace someone elses life in a positive way just as it had done mine. It's in very good condition and still looks brand-spanking new. The only thing that I need to ensure is that the phone is wiped clean - inside and out. Even though I carried out a factory reset, I read doing this alone is not enough to make your previously stored information fully un-recoverable.

    To be completely sure that the device has had a complete wipe down, you need to ensure the Android device is encrypted prior to carrying out the factory reset. You can check if the phone is set to be encrpyted by going into Settings > Security > Encryption. By doing this, the encryption process will scramble your data and if some data is left after the factory reset, a key would be required to unecrypt it. For the general user, this should suffice.

    I decided to take things a step further, just to be 100% sure. I found a very good post on StackExchange Security that states the following:

    Factory resets reset your phone to a stock like state but does not remove your data, just applications. This leaves some data behind. The best way to prevent this data from being recovered is to encrypt the phone, and use wipe data/factory reset from the recovery menu. This way you don't have to download a ton of data and you can be fairly certain your things are secure.


    If you're not that worried, encrypting, and data/factory reset from the recovery menu is probably enough.


    Forgot to mention why the recovery mode data/factory reset. It formats the user data areas as well as the application area, and is far more thorough/secure than the one inside of the android OS and will prevent you from download junk data. It just flat out gets rid of it.


    To get to the recovery console on the Nexus 5 for resetting:

    1. If your phone is on, turn it off.
    2. Press and hold the Volume Down and Volume Up buttons, and then press and hold the Power button at the same time until the phone turns on. You'll see the word "Start" with an arrow around it.
    3. Press the Volume Down button twice to highlight "Recovery."
    4. Press the Power button to start Recovery mode. You'll see an image of an Android robot with a red exclamation mark and the words "No command."
    5. While holding the Power button, press and release the Volume Up button once.
    6. Press the Volume Down button twice to highlight "wipe data/factory reset" and press the Power button to select it.
    7. Press the Volume Down button seven times to highlight "Yes - erase all user data" and press the Power button to select it.
    8. After the reset is complete, press the Power button to select the option to reboot your device.

    Don't forget to also revoke account access as an extra measure by logging into your Google Account and clicking the "Remove" button (https://security.google.com/settings/security/activity).

    Disconnecting Nexus 5 from Google Account

  • Published on
    -
    1 min read

    I am Just One Of Those Developers...

    ...who hasn’t created a new open-source plugin/library, answered many posts on StackOverflow (as much as I’d like to!), made an active contribution to Github, created a Pluralsight course, or coded something beautiful on CodePen.

    How very selfish of me.

    But what I do know is that this doesn’t make me any less of a developer. I have the capability to translate something in it’s infancy to truly something awesome that I am confident I will be very much proud of. I think as a developer that's quite easy to lose sight of - I know I feel that way. Just throw a problem or project my way and I’ll do it.

    Would I like to have the capability to everything I stated in my first sentence? Yes! Who wouldn’t? I look at my experienced peers (to whom I refer to as “the greats”) in pure admiration and hoping one day I will have the capacity to contribute to the programming world as they do.

    As I gaze back at my 8 years in the programming world, one thought comes to mind: I should be doing more. Thoughts like these is was what separates us from just being good at what we do to something much much more.

  • Over the last few months, I've been working away on a Kentico 9 EMS project. Very exciting indeed! Really pulling out all the stops on trying to make an amazing site in an EMS framework alongside the whole team at Syndicut.

    This week, I had to develop a custom built form to grab some user's information. Unfortunately, I was unable to use Kentico's Form Builder due to the requirement where the details had to be submitted to an external API, as well as utilising a custom design.

    One of the many benefits you get out-the-box from using the Kentico Form Builder is the ability to log marketing activity to the Contact Management area to store information on the visitors who view and interact with your site. By building a custom form, I was losing losing key data, such as: First Name, Last Name Email Address and Telephone No. - The base key criteria of turning an anonymous visitor to a person with some context.

    To avoid this loss of data, I created a method that uses the CMS.OnlineMarketingContext class to allow you to manually update the current visitor information:

    /// <summary>
    /// Creates/Updates a contact in Kentico's Contact Management system.
    /// </summary>
    /// <param name="firstName">Visitors first name</param>
    /// <param name="lastName">Visitors last name</param>
    /// <param name="emailAddress">Visitors email address</param>
    /// <param name="businessPhone">Visitors business phone number</param>
    /// <param name="allowContactOverwrite">Overwrite existing contact fields with new information.</param>
    public static void SetMarketingContact(string firstName, string lastName, string emailAddress, string businessPhone, bool allowContactOverwrite = false)
    {
        ContactInfo existingContact = OnlineMarketingContext.GetCurrentContact();
                
        // Update an existing contact or create a new one if no existing contact exists.
        if (existingContact != null)
        {
            existingContact.ContactFirstName = firstName;
            existingContact.ContactLastName = lastName;
            existingContact.ContactEmail = emailAddress;
            existingContact.ContactBusinessPhone = businessPhone;
    
            if (allowContactOverwrite)
                existingContact.Update();
        }
    }
    

    My code only shows a handful of fields that I am updating, but the "ContactInfo" class provides access to many more.

  • After a long blogging hiatus, I decided to make my somewhat grand return! So here we go...

    There are times when you need to retrieve documents from using the TreeProvider.SelectNodes() that can return DataRowViews or DataRows of node information. Now, Kentico provides "DataHelper.GetDataRowViewValue()" and "DataHelper.DataRowValue()" methods to output your required fields of information. But I find these DataHelper methods quite tedious when you have a massive collection of node data. I am lazy and would do anything to make my life easier.

    So I created a DataHelperExtension class object that would allow me to get my commonly used DataRow and DataRowView fields with ease:

    • Document ID
    • Class Name
    • Node Alias Path
    • Get String Value (for custom fields)
    • Get Integer Value (for custom fields)
    • Page Menu Name
    • Node Has Children
    public static class DataHelperExtensions
    {
        /// <summary>
        /// Get the Document ID.
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static int DocumentId(this DataRow dr)
        {
            return int.Parse(DataHelper.GetDataRowValue(dr, "DocumentID").ToString());
        }
    
        /// <summary>
        /// Get the document Class Name.
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static string ClassName(this DataRow dr)
        {
            return DataHelper.GetDataRowValue(dr, "ClassName").ToString();
        }
            
        /// <summary>
        /// Get Node Alias Path.
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="fullUrlPath"></param>
        /// <returns></returns>
        public static string NodeAliasPath(this DataRow dr, bool fullUrlPath = true)
        {
            if (!fullUrlPath)
                return DataHelper.GetDataRowValue(dr, "NodeAliasPath").ToString();
            else
                return DocumentURLProvider.GetUrl(DataHelper.GetDataRowValue(dr, "NodeAliasPath").ToString());
        }
    
        /// <summary>
        /// Get custom string field.
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static string GetStringValue(this DataRow dr, string fieldName)
        {
            if (DataHelper.GetDataRowValue(dr, fieldName) != null)
                return DataHelper.GetDataRowValue(dr, fieldName).ToString();
            else
                return String.Empty;
        }
            
        /// <summary>
        /// Get custom integer field.
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static int GetIntegerValue(this DataRow dr, string fieldName)
        {
            if (DataHelper.GetDataRowValue(dr, fieldName) != null)
                return int.Parse(DataHelper.GetDataRowValue(dr, fieldName).ToString());
            else
                return 0;
        }
            
        /// <summary>
        /// Get Menu Caption of a page, otherwise default to the Document Name.
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static string PageMenuName(this DataRow dr)
        {
            string menuCaption = DataHelper.GetDataRowValue(dr, "DocumentMenuCaption").ToString();
    
            if (String.IsNullOrEmpty(menuCaption))
                menuCaption = DataHelper.GetDataRowValue(dr, "DocumentName").ToString();
    
            return menuCaption;
        }
    
        /// <summary>
        /// Check if node has children.
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static bool NodeHasChildren(this DataRow dr)
        {
            return bool.Parse(DataHelper.GetDataRowValue(dr, "NodeHasChildren").ToString());
        }
    
        /// <summary>
        /// Get the Document ID.
        /// </summary>
        /// <param name="drv"></param>
        /// <returns></returns>
        public static int DocumentId(this DataRowView drv)
        {
            return int.Parse(DataHelper.GetDataRowViewValue(drv, "DocumentID").ToString());
        }
    
        /// <summary>
        /// Get the document Class Name.
        /// </summary>
        /// <param name="drv"></param>
        /// <returns></returns>
        public static string ClassName(this DataRowView drv)
        {
            return DataHelper.GetDataRowViewValue(drv, "ClassName").ToString();
        }
    
        /// <summary>
        /// Get Node Alias Path.
        /// </summary>
        /// <param name="drv"></param>
        /// <param name="fullUrlPath"></param>
        /// <returns></returns>
        public static string NodeAliasPath(this DataRowView drv, bool fullUrlPath = true)
        {
            if (!fullUrlPath)
                return DataHelper.GetDataRowViewValue(drv, "NodeAliasPath").ToString();
            else
                return DocumentURLProvider.GetUrl(DataHelper.GetDataRowViewValue(drv, "NodeAliasPath").ToString());
        }
    
        /// <summary>
        /// Get custom string field.
        /// </summary>
        /// <param name="drv"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static string GetStringValue(this DataRowView drv, string fieldName)
        {
            if (DataHelper.GetDataRowViewValue(drv, fieldName) != null)
                return DataHelper.GetDataRowViewValue(drv, fieldName).ToString();
            else
                return String.Empty;
        }
    
        /// <summary>
        /// Get custom integer field.
        /// </summary>
        /// <param name="drv"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static int GetIntegerValue(this DataRowView drv, string fieldName)
        {
            if (DataHelper.GetDataRowViewValue(drv, fieldName) != null)
                return int.Parse(DataHelper.GetDataRowViewValue(drv, fieldName).ToString());
            else
                return 0;
        }
    
        /// <summary>
        /// Get Menu Caption of a page, otherwise default to the Document Name.
        /// </summary>
        /// <param name="drv"></param>
        /// <returns></returns>
        public static string PageMenuName(this DataRowView drv)
        {
            string menuCaption = DataHelper.GetDataRowViewValue(drv, "DocumentMenuCaption").ToString();
    
            if (String.IsNullOrEmpty(menuCaption))
                menuCaption = DataHelper.GetDataRowViewValue(drv, "DocumentName").ToString();
    
            return menuCaption;
        }
    
        /// <summary>
        /// Check if node has children.
        /// </summary>
        /// <param name="drv"></param>
        /// <returns></returns>
        public static bool NodeHasChildren(this DataRowView drv)
        {
            return bool.Parse(DataHelper.GetDataRowViewValue(drv, "NodeHasChildren").ToString());
        }
    }
    

    Here's an example on how to put this DataHelperExtension class into use:

    if (!DataHelper.DataSourceIsEmpty(data))
    {
        DataView sortedData = data.Tables[0].DefaultView;
    
        foreach (DataRowView drvTestimonial in sortedData)
        {
            int docId = drvTestimonial.DocumentId(); // Get the Document ID
            string title = drvTestimonial.GetStringValue("Title"); // Custom field
    
            // Do something with the fields of data.
        }
    }
    

    Simple and effective!

  • Published on
    -
    1 min read

    It's Only Life

    I can totally relate to the this song right now: The Shins - It's Only Life.

  • Published on
    -
    2 min read

    Pen + Paper = Productivity

    I was fuelled into writing my own views upon reading a very interesting post by Scott Hansalman, where he argues that we would all be more productive and stress free if we were to assimalate all our thoughts and ideas to paper rather than to an electronic device. I was intrigued by Scott's argument and he brings up many valid points that I agree with.

    I for one have been addicted to taking notes on electronic devices from the very first day I used Evernote on my old HTC Hero. There has been no other note taking application that has organised my thoughts in such a way. In fact, majority of the blog posts I write start out in Evernote for wherever I have a spark of imagination. You can read how profoundly Evernote has affected my life in a post I wrote last year.

    Note Taking

    Now, as great as Evernote is, it suffers from one problem (same for any other note taking app for that matter): They stifle the flow of free thinking. Scott Hansalman sums this up quite well:

    The problem is, at least for me, is that there isn't a great way to see the big picture when you've just got pixels to look at. Life is much higher resolution than I think folks realize. I'm frankly surprised that so many of you can feel organized and productive on those 11" laptops. What a tiny window into your life!

    Scott hits the nail on the head. I too feel the same way. Paper has no fixed structure that you are forced to conform to, which makes processing your own thoughts very easy. Unfortunately, software for note taking has not advanced nearly as fast. It's still all too linear and fixed.

    What is the happy medium? Can software applications and conventional note taking work hand in hand? I believe it can. Notes I either jot down from client meetings or from just simply brainstorming will always be scanned, tagged and organised to Evernote. This allows me to store my hand-written notes away safely and easily refer back to them through a simple keyword search.

    I do like to write (even if my writing is not exactly legible). Whether I'd be making notes or the odd doodle, either way writing is a very cathartic experience. I'll always get more of a kick crossing out completed tasks from a hand-written todo list then I ever would from simply ticking a checkbox within an application.

    Pen is not only mightier than the sword, but also mightier than any form of technological device.

  • There are many things that impress me about Kentico, especially when I compare my experiences to other CMS providers from previous walks of life. But the one thing that impresses me above all is how easy the guys at Kentico make upgrading to newer versions of their CMS platform. So I wasn't daunted when I had the job to upgrade a site from Kentico 5.5 all the way up to 8.2.

    Everything went smoothly. I was in the last leg of the upgrade process where the site had been upgraded to version 7 and was about to make the transition to 8. At this point, I started encoutering issues...

    Upgrading from version 7 to 8 alone is a very big jump and you will find that getting your site fully functional will require more effort than all the previous upgrades combined - depending on the size and complexity of your Kentico instance. Take a look at the "Upgrade Overview" section in the Kentico upgrade documentation for a list of important changes.

    I decided to list some quite important steps based upon information I have collated from issues others have experienced as well as key points covered within the Kentico Upgrade documentation. Following the points listed below resolved my upgrade issues, so it will more than likely help you too.

    1) Clear Browser Cache

    After each upgrade, remember to always clear your browser of all temporary files stored in cache and old cookies prior to logging into the Administration Area. Otherwise you will more than likely see a mish-mash of old/new graphical elements, as well as an Internal Server Error popup.

    Kentico 8 Upgrade - Internal Server Error

    2) Run The Site After Each Upgrade

    This is something I've had a tendency to forget. It is imperative that you run the site after each upgrade before moving onto the next, since Kentico requires code to be executed as well as database tasks.

    3) Update Macro Signatures

    This is an easy one. You'll probably see a bunch of Macro security errors in Kentico's Event Log post upgrade like these:

    Kentico 8 Upgrade - Macro Resolver Error

    Luckily, this is easily resolved by simply updating the macro signatures in the System > Macros > Signatures area of within the CMS Administration.

    Kentico 8 Upgrade - Sign Macros

    The system then resigns all macros. The new security signatures of all macros contain the username of your administrator account.

    4) Re-save All Page Types

    This is a strange one. For some odd reason, I experienced the same Internal Server Error popup message when logged into the CMS as described in point 1. In addition, I found when attempting to navigate directly to the website, I would get an Object not set to an instance of an object.NET error whenever a "DocumentContext.CurrentDocument" call was made.

    So I decided to randomly try something Kentico master Juraj suggested from one of his forum responses, which was to add and then remove a field from a document type. Instead, I just went to the Field section of each Page Type and clicked the "Save" button.

    I have no idea what difference this makes within the Kentico setup but this seems to do the trick.

    5) Custom Modules Created In Version 7

    If you have developed any custom modules, ensure you have marked them as "custom" before upgrading to version 8. I had numerous upgrade failures when Kentico Installation Manager was trying to upgrade the database. The error occurred in the CMS_UIElement table due to duplicated Element Resource ID's.

    You can mark your custom module as "custom" in version 7 by going to: Site Manager > Development > Modules > Your Custom Module > User Interface.

    Kentico 7 - Setting Element Is Custom

    6) Check Data & DB Versions

    After you have run an upgrade for each major version (6.0, 7.0, 8.0, 8.2), make sure you run the following SQL query against your Kentico database:

    SELECT
        KeyName, KeyValue
    FROM
        CMS_SettingsKey
    WHERE
        KeyName IN ('CMSDBVersion', 'CMSDataVersion')
    

    If both values for "CMSDBVersion" and "CMSDataVersion" are the same, you know the upgrade has successfully completed and you're on the right track. When I made my first attempt to upgrade a site from 7 to 8, I found the Data Version was 7.0 and the DB Version was 8.2. Not good.

    Useful Links

  • ...and I think I know why...

    Out of all the issues Google PageSpeed Insights seems to have when analysing my site, there are two specific things crop up that annoy me:

    1. ​Reduce server response time
    2. ​Leverage browser caching (due to Google Analytics JavaScript file)

    The Google Analytics issue is something I will have to live with since (as far as I'm aware) there's nothing I can do. It would be nice if Google wouldn't penalise you for using a product they have developed. However, the "Reduce server response time" was something that perplexed me. My site is relatively simple and not doing anything over-the-top.

    Due to the nature of my hosting setup (shared), I didn't have all the capabilities to make my website respond any better. The only way I could think of improving server response time was to move my hosting to another region and purchasing a VPS to get more control.

    Now, I think I have resolved the server response time issue...It has something to do with a Web Statistics service called AWStats that was enabled by default as an "addon" service on my hosting. Once disabled through my Plesk Management Portal, Google PageSpeed didn't seem to have any issue with my server response.

    I cannot 100% confirm if by disabling the Web Statistics service is a permanent solution and will work for everyone else. But there might be some truth behind this. Web Statistic services like AWStats store all analytical data in log files directly on the server, so this must have some affect on the time a request is made. I could be talking complete nonesense.

    If you have experienced the same problem as me, check your own hosting setup and it's "addon" services. You never know, it may give you that extra Google PageSpeed point. :-)

  • I've just completed working on a site that required PayPal integration to carry out credit card payments, using PayPal's REST API interface. I did find some aspects of the implementing PayPal's REST API a little confusing and there seemed to be a blurred line on what is the best approach. This is probably due to the vast number of .NET examples provided in PayPal's own Github repository.

    I decided to create my own PayPal REST API .NET Starter kit, by combining my own efforts together with PayPal documentation and code examples from other developers online. Feel free to fork it from my Bitbucket repository: https://bitbucket.org/SurinderBhomra/paypal-.net-starter-kit.

    The PayPal REST API .NET Starter kit contains everything you need to make a start in making your first card payment. It encompasses a very basic form to enter test transactions, as well as the following Nuget package references:

    • log4net
    • Newtonsoft.Json
    • PayPalCoreSDK
    • RestApiSDK

    All you'll need to do is create is a PayPal Client ID and Secret, build the solution and away you go. Every time you make a transaction, a "PaypalPayment" object is returned, containing useful information to be used at application level if the payment was a success and if not, the full error information.

    A successful transaction will generate the following invoice to the user's PayPal account:

    PayPal Invoice Sample

    I am using my PayPal Starter kit as a foundation to build upon if I ever get the opportunity to develop more features, such as refunds.

    Feel free to modify my code and (even better!) add more features.