Why Clydesdale?
Expertise
Strategic Partners
Blog
Contact
Home
Clydesdale Software Logo

Clydesdale Software, Inc.

355 South Teller St.

Suite 200

Lakewood, CO 80226

info@ClydesdaleSoftware.com


Follow Us: Twitter RSS



  • More With the Azure Cache

    In my last post I showed how I fixed a ton of errors that were being received with a very simple approach for working with the Azure Cache.

    This time I will share how I dealt with serialization issues because I decided to add a property to an object I stored in the cache then deployed, BOOM.

    Another simple approach, when an error happens trying to get the item from the cache (then casting it), remove that item from the cache and the next call will add it back in and life will go on.  If you do not do this the item will be attempted to be retrieved many times each throwing an exception.

     

    EXAMPLE

    public static CustomerInfo GetCustomerInfoByAccessKey(string accessKey)
    {
                if (RoleEnvironment.IsAvailable)
                {
                    try
                    {

                       //GetCacheItem is the method from my previous post
                        var customerCacheItem = GetCacheItem(accessKey);

                        if (customerCacheItem == null)
                        {
                            var customer = RetrieveCustomerInfoByAccessKeyFromDB(accessKey);

                            if (customer != null)
                            {
                                DataCache.Put(customer.AccessKey, customer, TimeSpan.FromHours(2));
                            }

                            return customer;
                        }
                        else
                        {
                            return (CustomerInfo)customerCacheItem.Value;
                        }
                    }
                    catch (Exception ex)
                    {

                        //Trys to Remove (i.e. the remove is in a try/catch) the

                        //CustomerInfo object related to the accessKey from the cache
                      
    FlushCustomer(accessKey);

                    //I want to know this happened
                        Log.Error("Caching Error: " + ex, CategorySources.Caching);
                    }
                }

                //Either not running in azure or emulator or the try to get it form the cache has failed

                return RetrieveCustomerInfoByAccessKeyFromDB(accessKey);
      }

    Full story

    Comments (0)

  • Choose Your Demographic Wisely

    When building a product make sure to think hard about your demographic.  The common mistake is to try and hit all your demographics at once and not putting much effort behind any one of them.

     

    From a product perspective, the  product is likely to become marginal in all the demographics with this approach and the feedback is so diverse the development of the product now becomes hindered.  It actually creates a cycle that is hard to break.

     

    hit all demographics  -> feedback from all demographics – > develop to all demographics –> hit all demographics –> Rinse and Repeat

     

    Result is not a product that is everything to everyone but a product that is marginal to everyone.

     

    Focus on one demographic while sampling others to gain analytics that an educated decision can be based on resulting in a much clearer direction.

    Full story

    Comments (0)

  • Azure Cache: DataCacheException –SOLVED!

    I have found a simple solution to the azure caching issue.  First off the error of  SubStatus<ES0006> which is throttled is not true.  The real issue is stale connections (I think).  When the cache is not used for a bit the connections go stale, then when you try to use them they throw the throttled exception again and again and it seems to take some time for it to stop being used and a new one created. 

    The solution/work around is to try and get the cache item once and if it fails recreated the cache object then go for the cache object.  Before I put this in place I got hundreds of errors.

    The code:

    Instead to using the DataCache’s GetCacheItem use this one.

    private static DataCacheItem GetCacheItem(string key)

            {

                try

                {

                    //See if the cache connections are valid

                    return DataCache.GetCacheItem(key);

                }

                catch

                {

                    //This is an attempt to get fresh connections everytime

                    InitCache();

                }

                return DataCache.GetCacheItem(key);

            }

    And the InitCache:

    private static void InitCache()

            {

                lock (lockObject)

                {

                    var cacheFactory = new DataCacheFactory();

                    var cache = cacheFactory.GetDefaultCache();

                    instance = cache;

                }

            }

    Instance and lockObject are fields:

    private static DataCache instance;

    private static readonly Object lockObject = new object();

    And for other cache operation such as puts I have this property:

    private static DataCache DataCache

            {

                get

                {

                    if (instance == null)

                    {

                        InitCache();

                    }

                    return instance;

                }

            }

    The Result

    Now no emails about this error and throughput has increased because only the first request fails with the cache then recreates the cache object and everything runs smoothly.

    Full story

    Comments (2)

  • Umbraco in Azure

    I’m sure I’m not the only one that started looking for a better way to have Umbraco in Azure then using the Umbraco Accelerator that hits blob storage every second.  There are many limitations to the accelerator and after spending a day modifying it I decided to go another direction.


    Firstly understand my usage scenario may not be the same as others.  I use a CDN for public content (such as images) and I created a handler to retrieve private content (such as user downloads) from blob storage.  For css, master page changes, etc I deploy then vip swap.  Quite honestly this is not what I use Umbraco for.  I do not upload images or private content to Umbraco so I do not need file syncing at the moment, though I do have some ideas on how to achieve this with notifications and web services.


    The main issue is Umbraco Caching.  When content is published it needs to notify all the instances in Azure so the cache can be updated.


    Umbraco supports load balanced environments so the trick is setting it up in Azure.


    1) Add <Runtime executionContext="elevated" /> to your service definition right under the WebRole element.


    2) Make sure umbracoUseSSL in the web.config appSettings is set to false.  The reason for this is each server listed in the umbracoSettings.config has a webservice called made on it.  The internal Umbraco code uses this setting and will try to use https for this call and since these are internal ips there will be a cert error and it will not work.  You can still access the admin portal with https, it will just not auto redirect (could probably use url rewriting to get around this).


    3) In umbracoSettings.config enable distributedCall.


    4) Use the UmbracoAzureSetup class to get load balancing setup. Add UmbracoAzureSetup.Setup() to your OnStart of the WebRole.

    NOTE 1: Please read through the UmbracoAzureSetup class because it is coded with some limitations that may require a code change to meet your requirements.

    NOTE 2: I recommend wrapping your code in OnStart in a try/catch and write to the event log on error so you can get details when something goes wrong.

    5) Enjoy Umbraco in Azure and watch caching work like a charm.


    Details of the UmbracoAzureSetup Class:

    This class is pretty simple, it does two basic things.  One, sets full control permissions for NETWORK SERVICE and two, updates the umbracoSettingsConfig with the ip addresses of the instances in Azure.


    // ----------------------------------------------------------------------------------
    //  Unified Logging
    // 
    //  Copyright (c) UL Analytics, LLC. All rights reserved.
    // 
    //  ----------------------------------------------------------------------------------

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Security.AccessControl;
    using System.Xml;
    using System.Xml.Linq;
    using System.Xml.XPath;
    using Microsoft.WindowsAzure.ServiceRuntime;

    namespace UnifiedLogging.Web.Site
    {
        public static class UmbracoAzureSetup
        {
            #region public Static Methods

            /// <summary>
            /// Sets up umbraco for load balancing in Azure.
            /// Things to Note:
            /// 1) This is coded to work with one Site element under Sites in the RoleModel.xml.
            /// Update the code if this is not your case.
            /// 2) Sets permissions for NETWORK SERVICE, if the app pool is different update the code.
            /// </summary>
            public static void Setup()
            {
                SetPermissions();

                UpdateUmbracoSettings();
            }

            #endregion

            #region private Static Methods

            /// <summary>
            /// This will get the attribute of the first Site under Sites in the RoleModel.xml. 
            /// If there are multpile site elements be sure to update this method to return the correct physical path.
            /// </summary>
            /// <returns></returns>
            private static string GetWebSiteDirectory()
            {
                var rootPath = string.Empty;

                var roleRootDir = Environment.GetEnvironmentVariable("RdRoleRoot");

                var roleModelDoc = XDocument.Load(Path.Combine(roleRootDir, "RoleModel.xml"));
                var namespaceManager = new XmlNamespaceManager(new NameTable());
                namespaceManager.AddNamespace("empty",
                                              "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition");

                var siteElement = roleModelDoc.XPathSelectElement("/empty:RoleModel/empty:Sites/empty:Site",
                                                                  namespaceManager);

                if (siteElement != null)
                {
                    var attr = siteElement.Attribute("physicalDirectory");
                    if (attr != null)
                    {
                        rootPath = Path.Combine(roleRootDir, attr.Value);
                    }
                }

                return rootPath + Path.DirectorySeparatorChar;
            }

            /// <summary>
            /// Will set full control permissions for NETWORK SERVICE on the entire web directory.
            /// </summary>
            private static void SetPermissions()
            {
                var roleRootDir = GetWebSiteDirectory();

                if (String.IsNullOrEmpty(roleRootDir) == false)
                {
                    roleRootDir = roleRootDir.TrimEnd('\\');

                    var accessControl = Directory.GetAccessControl(roleRootDir);
                    accessControl.AddAccessRule(new FileSystemAccessRule("NETWORK SERVICE", FileSystemRights.FullControl,
                                                                         InheritanceFlags.ContainerInherit |
                                                                         InheritanceFlags.ObjectInherit,
                                                                         PropagationFlags.None,
                                                                         AccessControlType.Allow));

                    Directory.SetAccessControl(roleRootDir, accessControl);
                }
            }

            /// <summary>
            /// Updates the umbracosetting.config with the ip addresses of the instances in the role.
            /// </summary>
            private static void UpdateUmbracoSettings()
            {
                var serverIps = new List<string>();

                if (RoleEnvironment.IsAvailable)
                {
                    foreach (RoleInstance roleInstance in RoleEnvironment.CurrentRoleInstance.Role.Instances)
                    {
                        foreach (RoleInstanceEndpoint endpoint in roleInstance.InstanceEndpoints.Values)
                        {
                            var ipString = endpoint.IPEndpoint.Address.ToString();

                            if (serverIps.Contains(ipString) == false)
                            {
                                serverIps.Add(ipString);
                            }
                        }
                    }
                }

                WriteDistributedServers(serverIps);
            }

            private static void WriteDistributedServers(List<string> serverIps)
            {
                var websiteRoot = GetWebSiteDirectory();
                //taken from umbraco source:)
                var configPath = websiteRoot + "config" +
                                 Path.DirectorySeparatorChar + "umbracoSettings.config";

                var umbracoSettings = XDocument.Load(configPath);
                var serversElement = umbracoSettings.XPathSelectElement("/settings/distributedCall/servers");

                if (serversElement != null)
                {
                    serversElement.RemoveNodes();

                    foreach (var serverIp in serverIps)
                    {
                        var serverElement = new XElement("server", serverIp);
                        serversElement.Add(serverElement);
                    }

                    umbracoSettings.Save(configPath);
                }
            }

            #endregion
        }
    }

    Full story

    Comments (0)

  • Will the US Government Open Their Eyes?

    I’m in complete disbelief how naive the US Government is these days by trying to take 35% of US companies profits and then surprised when some of our largest companies move their business elsewhere and take their money with them.

     

    The US Government’s response is to create more tax laws trying to force companies to pay taxes and close loopholes.  This is not rocket science, basic toddler behavior, the more rules you try to enforce the more erratic and undesirable behavior results. Maybe the US politicians have never raised a kid or they have not watched enough star wars. Give companies a reason to stay, incentivize them.

     

    So the US is currently willing to accept 0% of profits and stick by their laws instead of accepting something less than 35% and incentivize companies to stay in the US. Seems pretty bull headed to me, but who am I to say; oh wait I’m one of the millions paying our politicians salaries!

     

    In conclusion, it seems the US government has forgotten that our nation is built on top of our people not our policies and laws.

    Full story

    Comments (0)

  • Thecus vs Drobo, and the Winner Is

    I will not keep you waiting, the winner is easily the Thecus N5500.

     

    Started out purchasing the Drobo FS with high hopes it would suite all my needs.  Well first pitfall which was a deal breaker is there is no Active Directory or LDAP integration.  Drobo support says this is because they are targeting the small office.  I call Bull Sh#$, plenty of small offices have active directory and are using small business server.

     

    So back the Drobo went and I ordered the Thecus N5500.  Once I got the N5500 I dropped in five 1TB drives configured in RAID 6 and away I went.  The web interface is great and setting permissions on folders is very simple.  Performance is good and I expect it to even be better once I setup link aggregation.

     

    So far the Thecus N5500 has done everything with ease I have asked of it.





    Full story

    Comments (0)

  • Rally Custom App: Release Estimation Board

    I love the estimation board in Rally but I dislike that it shows everything.  I wanted to have it filter by release so here is the custom app that you can add that does just that.


    Full story

    Comments (0)

  • Sonos Review

    Since the turn of the century I have been looking for a music system that was an easy to use mutli room audio system.  Is Sonos the answer?

     

    Well, yes and no depending on your setup.  Here are some simple things you need to know.

     

    • - UPnP must be support by your router
    1. - A 2.4 GHz Network is required (or at least I could not get it to work on my 5 GHz network)

    I’m sure many of you meet these requirements but I did not and it took me a some time to come up with a solution.  First off I run a business class network on a Cisco ASA 5505 security appliance which it turns out does not support UPnP.  So I could either ditch the Cisco ASA or bring up another network router that supports UPnP.  I opted to ditch Cisco, it has been a love/hate relationship with the ASA and I decided to just use the E3000 router instead which supports UPnP.

     

    Next when I tried to use the Sonos controller on my iPad 2 it could not find the Sonos Bridge but when I used my iPhone 3GS it worked great.  The difference, one uses the 2.4 GHz network and one uses the 5GHz network.  Once I switched the iPad 2 to use the 2.4 GHz network it worked like a charm.

     

    I really am sideways about Cisco not support UPnP as there are plenty of small business that use an ASA security appliance and want to have music in their waiting room or somewhere else.

     

    Now that things are setup it works great!  I’m loving the Sonos but when will Cisco support UPnP on the ASA security appliance so I can use it again… or maybe I will end up switching to another router that supports multiple public ip’s and UPnP.

    Full story

    Comments (0)

  • Sitefinity 4.0 Migration–Blog Posts

    Anyone who has migrated from Sitefinity 3.7 to 4.0 and have had a blog has quickly realized all the post dates are wrong.  The correct dates are in the database but they are not the published dates you are seeing.

     

    I wrote a quick sql script to correct this.  Run the script after publishing the posts to update the date to the date that should be displayed.

     

    create table #temp
    (
        content_id uniqueidentifier,
        publication_date datetime
    )

    insert into #temp
    SELECT content_id, publication_date
    FROM sf_blog_posts
    WHERE content_state = 'PUBLISHED'

     

    UPDATE sf_blog_posts
    SET publication_date = #temp.publication_date
    FROM sf_blog_posts
    INNER JOIN #temp
    ON #temp.content_id = sf_blog_posts.original_content_id
    WHERE sf_blog_posts.original_content_id = #temp.content_id


    drop table #temp

    Full story

    Comments (0)

  • Sitefinity 4.0, What did Telerik Do?

    At first I was very excited to move from Sitefinity 3.7 to 4.0 but…  After going through the migration process using the less than exceptional codeplex migration project I started to realize this was not a fully baked product.  The migration process feels like a complete afterthought, case and point the blog posts post dates are not migrated correctly (the real issue is with there api for the blog, follow-up post to follow).  All 3.7 sitefinity images do not work, could be a hassle for sites with large number of pages with sitefinity images on them.

     

    I feel like Sitefinity team has forgotten about their current customers.  Like many current Sitefinity customers there is a fair amount of custom coded widgets and navigation that were created in 3.7 because it was just so easy to extend.  In 4.0 nothing works because 4.0 is a new version 1 product.

     

    Where did they go wrong? 

    First off they need more custom code examples.  This was fantastic in 3.7, all the Sitefinity team had to do is look at what guidance already existed for 3.7 and create it for 4.0.

     

    The left out what I consider foundational functionality such as having pages be defined as links to another page either internally or externally.  Another biggie is not shipping a Lists module, this is a basic construct that humans have used since caveman days and there is even a computer language based on this (lisp).  So why have cavemen figured out how important lists are but the Sitefinity team was quick to dismiss it from there 4.0 initial delivery, there is a big lesson learned here that I hope they take the opportunity to realize.

     

    This is for the Sitefinity team

    A product is more than what's gets shipped.  The guidance, sales, marketing, branding, customer support, etc. are all part of successfully shipping a product.  In short this product was shipped 3-6 months too early and I’m sure your customer service team is paying the price for it now.

    Full story

    Comments (0)

  • Daily Telerik WTF

    - User Submit bug/question to Telerik Sitefinity group

    - User receives answer that does not address the question but does elude to an existing ticket number

    - User receives response from support saying “Like I said look at ticket number ######”

    - User Responds: OK, where do I find ticket number #####

    - Support Responds:  Tickets are internal only

    Full story

    Comments (0)

  • The Power of Humility

    Adding a little bit of humility to ones character can go a long way to enhance your personal power.

     

    A great example of this is Lance Mackey, his humility makes him very likeable and it strengthens his personal power as shown in the 2008 Iditarod when he snuck out ahead of Jeff King while he was sleeping.  No one woke Jeff King because of Lance Mackey’s person power.

     

    The opposite is the case with Jeff King.  He says things like, “I’m the guy people wish they could be” which definitely lowers his personal power and instead of humility he shows arrogance.

    Full story

    Comments (0)

  • Remote Desktop and Local Resources

    Learned a valuable lesson the other day.

     

    Scenario:  Copy/Paste on a remote server was extremely slow.  So slow it took 45 minutes to copy and paste 50 MB from one folder to another on the same server and same drive.

     

    The Problem and Solution:  In my connection profile for that server I had my C: drive checked as a local resource.  I did not even remember doing this.  Well even though I was not copying/pasting anything from my local computer it was routing the operation through my remote connection.  Once I unchecked the C: from the local resource it was lightening fast again.

    Full story

    Comments (0)

  • SQL Server 2008 R2 is Getting More Useful

    Good News, SQL Server 2008 R2 supports database sizes up to 10GB!

    Full story

    Comments (0)

  • Stop the Chaos: The Gold Build

    Delivering great software is not a race to the finish line (by finish line I mean deployment to production).  Instead mark your acceptable builds as Gold Builds and when the business is ready to have it deployed, deploy the latest gold build.

     

    There will always be a push to get more done with less.  Using gold builds will alleviate the stress of trying to hit a deadline and having the go no go call the day before go live.  Another very important side effect of managing builds and deployment this way is the number of bugs released into production goes down.  Most likely this is due to the decrease in stress and increase in time to make sure the pinned gold build is truly the one to go live.

     

    Sounds easy but it is hard because setting the expectations with the business, sales, marketing even IT can be hard if the expectations are left uncontrolled.

    Full story

    Comments (0)

  • Little Bits of JavaScript – YUI Library

    Just wanted to share something I ran across the other day.  If you are looking for a great set of utilities and controls, written with JavaScript and CSS then check out YUI Library.

    Full story

    Comments (0)

  • Turning Internal Wants into External Needs

    Everyone hears it all the time, an internal staff member saying they want something.  There is nothing wrong with this but put the time in to do the research to make sure the internal want really has an external need.

     

    Just for clarification, external need = customer need.

    This can be as simple as a conversation of how the internal want will make your customers lives easier but it could very well uncover something bigger.  Or, it may uncover that the internal want has no validity at all.

    Full story

    Comments (0)

  • Simple Tip #27: Trade Show Basics

    Here are some quick tips to make your next trade show a great one!

     

    Good Booth:  Don't need to spend a lot of money but do need to stand out.  Practice setting up prior to shipping to the show.  Be sure to allow plenty of time for shipping to eliminate stress.

     

    Booth Location: Helpful if you sponsor

     

    Food:  Key in drawing people in - sparkling wine and sandwiches

     

    Hostess:  Necessary for an international trade show

     

    Speak at every show:  Almost the most important part.  Traffic really picks up after a speech.

     

    Sponsor:  Great advertising, excellent opportunity to getting a good spot.

     

    Cocktail party:  Invite only but have invites at the booth for impromptu invite.

     

    Systematically capture all leads:  Wordpress has a plugin for SalesForce

     

    Follow up on all leads:  Analyze all leads and identify who should follow up and how.  Needs to be timely.

    Full story

    Comments (0)

  • Tie Your Business Strategies Back To Your Customers

    It is much easier to think about yourself than to think about others.  Believe it or not this is what most companies do, they think of themselves when making decisions and never tie it back to their customers.

     

    So take a moment to step back and ask “How does this affect our customers?”

    Full story

    Comments (0)

  • QA Needs to Step Up

    I’m really tired of hearing tales of QA departments waiting on development and being a second class citizen in the software development process.  QA needs to mean quality assurance not testers.

     

    I would love to see the day when QA steps up and drives the software development process instead of development.  Developers should be going to QA to ask questions of how something should work.  QA should be working on tests before development even starts on a feature.

     

    You can probably pick up on my disgust on this.  I truly believe the roles of QA and development need to be reversed and Quality Assurance should drive software development.  Obviously both QA and development are always a part of the bigger picture with business stakeholders driving the direction of product and company.

    Full story

    Comments (0)

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. Next page