Friday, 18 July 2014

Implementing a fast point structure in C# for large-scale comparison checks and searches

The code below is extracted from Part I of the Pluralsight course "Making .NET Applications faster", discussed and presented below. Implementing a fast structure for 2D points in C# requires using a struct instead of a class, since this is value-based and not reference type, i.e making use of the stack and not the heap and avoiding expensive header fields of objects. In addition, it is necessary to:
  • Override the Equals method inherited from System.Object
  • Implement a method called Equals that returns true and has one input parameter, another instance of the same struct
  • Mark the struct with the generic IEquatable interface, IEquatable<PointV5>
  • Implement the operators == and != to make use of the Equals method receiving an instance of the struct
  • Implement GetHashCode, using Jon Skeet's advice of creating a weighted sum multiplied by prime numbers and the struct's fields
Implementing this equality regime will reduce overall size in memory about 4x and increase speed 4x to 10x for large scale scenarios. In the example code testing this code, 10 million 2D point structs of type PointV5 was tested. Most modern games will avoid reference types of course and stick to value types, i.e. structs. Since most of us are application developers, make sure if you create a LOT of objects, consider switching from class to struct type(s), if possible. Often, it is not needed to use classes, a struct will be sufficient (and faster and lighter). Check out the course page here: Pluralsight: Making .NET applications faster Pluralsight is a great course and IT resource for IT professionals!

using System;


    struct PointV5 : IEquatable
    {
        public int X;
        public int Y;

        public override bool Equals(object obj)
        {
            if (!(obj is PointV5)) return false;
            PointV5 other = (PointV5)obj;
            return X == other.X && Y == other.Y;
        }

        public bool Equals(PointV5 other)
        {
            return X == other.X && Y == other.Y;
        }

        public static bool operator ==(PointV5 a, PointV5 b)
        {
            return a.Equals(b);
        }

        public static bool operator !=(PointV5 a, PointV5 b)
        {
            return !a.Equals(b);
        }

        public override int GetHashCode()
        {
            // 19 and 29 are primes, and this doesn't assume anything about
            // the distribution of X and Y.
            // Also see http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
            int hash = 19;
            hash = hash * 29 + X;
            hash = hash * 29 + Y;
            return hash;
        }
    }


Actually, a simple class is in fact faster in this scenario, according to the testing I did. Consider this class:

public class PointV0
{

        public int X { get; set; }

        public int Y { get; set; }

}

However, the price on pays here is higher memory overhead, as each point will have to be stored on the heap and have the object header fields and method table pointer fields, i.e. taking up more memory.

Elementary class
        Average time per lookup: 85,70ms
        Garbage collections: 0
Naked struct
        Average time per lookup: 435,10ms
        Garbage collections: 1018
With Equals override
        Average time per lookup: 248,70ms
        Garbage collections: 510
With Equals overload
        Average time per lookup: 239,50ms
        Garbage collections: 510
With IEquatable
        Average time per lookup: 168,60ms
        Garbage collections: 0
All bells and whistles
        Average time per lookup: 170,00ms
        Garbage collections: 0
Press any key to continue ..

I cannot conclude from these results that structs always are faster than classes, but it will always be more memory overhead to resort to classes instead of structs.. It looks though, that in this example, a simple class was the fastest choice!

Wednesday, 25 June 2014

A generic IEqualityComparer of T written in C#

When working with LINQ, often one has to pass in an IEqualityComparer of the class(es) being used. Implementing IEqualityComparer on classes can sometimes be unwanted to just make the computations work, therefore a generic implementation would be nice to invoke when performing the LINQ expression without either adding IEqualityComparer or worse - having to rewrite it. Sometimes also multiple implementations are desired.. The following class LambdaComparer is a generic implementation of IEqualityComparer of T.


using System;
using System.Collections.Generic;

namespace Hemit.OpPlan.Client.Infrastructure.Utility
{
    /// <summary>
    /// LambdaComparer - avoids the need for writing custom IEqualityComparers
    /// 
    /// Usage:
    /// 
    /// List<MyObject> x = myCollection.Except(otherCollection, new LambdaComparer<MyObject>((x, y) => x.Id == y.Id)).ToList();
    /// 
    /// or
    /// 
    /// IEqualityComparer comparer = new LambdaComparer<MyObject>((x, y) => x.Id == y.Id);
    /// List<MyObject> x = myCollection.Except(otherCollection, comparer).ToList();
    /// 
    /// </summary>
    /// <typeparam name="T">The type to compare</typeparam>
    public class LambdaComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> _lambdaComparer;
        private readonly Func<T, int> _lambdaHash;

        public LambdaComparer(Func<T, T, bool> lambdaComparer) :
            this(lambdaComparer, o => 0)
        {
        }

        public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
        {
            if (lambdaComparer == null)
            {
                throw new ArgumentNullException("lambdaComparer");
            }

            if (lambdaHash == null)
            {
                throw new ArgumentNullException("lambdaHash");
            }

            _lambdaComparer = lambdaComparer;
            _lambdaHash = lambdaHash;
        }

        public bool Equals(T x, T y)
        {
            return _lambdaComparer(x, y);
        }

        public int GetHashCode(T obj)
        {
            return _lambdaHash(obj);
        }
    }
}


The following unit tests uses this implementation of a generic IEqualityComparer of T:

using System;
using System.Collections.Generic;
using System.Linq;
using Hemit.OpPlan.Client.Infrastructure.Utility;
using NUnit.Framework;

namespace Hemit.OpPlan.Client.Infrastructure.Test.Utility
{
    
    [TestFixture]
    public class LambdaComparerTest
    {

        [Test] 
        public void LambdaComparerPerformsExpected()
        {
            var countriesFirst = new List<Tuple<int, string>>{ 
                new Tuple<int, string>(1, "Spain"),
                new Tuple<int, string>(3, "Brazil"),
                new Tuple<int, string>(5, "Argentina"),
                new Tuple<int, string>(6, "Switzerland"),
                new Tuple<int, string>(7, "Uruguay"),
                new Tuple<int, string>(8, "Colombia")
            };
            var countriesSecond = new List<Tuple<int, string>>{
                new Tuple<int, string>(1, "Spain"),
                new Tuple<int, string>(4, "Portugal"),
                new Tuple<int, string>(7, "Uruguay"),
                new Tuple<int, string>(10, "England"),
                new Tuple<int, string>(11, "Belgium"),
                new Tuple<int, string>(12, "Greece")
            };

            var expected = new List<Tuple<int, string>>
            {            
                new Tuple<int, string>(3, "Brazil"),
                new Tuple<int, string>(5, "Argentina"),
                new Tuple<int, string>(6, "Switzerland"),               
                new Tuple<int, string>(8, "Colombia")                
            }; 

            var countriesOnlyInFirst = countriesFirst.Except(countriesSecond, new LambdaComparer<Tuple<int, string>>((x, y) => x.Item1 == y.Item1));

            CollectionAssert.AreEqual(countriesOnlyInFirst, expected); 

        }


    }


}


In the unit test above, two lists containing the topmost FIFA ranking country teams in soccer in the world are being used in a LINQ Except expression, where the generic LambdaComparer class is being used. The class being passed in is Tuple of int and string: Tuple<int,string> - Note that an ordinary class could also be used here. The property Item1 of the Tuple is the "key" that is being used to compare two different objects - if it is the same, the objects are being considered to be the same. This results into a list of items from the first country list that are not being present in the second list. Finally, a list of the expected result is being built up and the NUnit CollectionAssert.AreEqual method is used for checking consistent result. The test passes. Much of .NET requires implementing interfaces such as IEqualityComparer, IComparer and more. Using a generic implementation class that expects Func expressions (the lambda expressions being passed, is a pattern that can give much flexibility.

Wednesday, 7 May 2014

Generic type conversion in C#

Generic type conversion in C# is possible, but the type conversion must consider many different conversions. The following code below defines a generic method To<T> which is an extension method on object:

namespace Hemit.OpPlan.Common
{
    
    public static class ObjectExtensions
    {

        public static T To<T>(this object value)
        {
            if (value == null)
                return default(T);

            Type t = typeof(T); 

            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                Type valueType = t.GetGenericArguments()[0];
                if (value == null)
                    return default(T);
                object result = Convert.ChangeType(value, valueType);
                return (T)result;
            }
            else if (typeof(T).IsEnum)
            {
                object result = Enum.Parse(typeof(T), value.ToString());
                return (T)result;
            }
            else
            {
                try
                {
                    object result = Convert.ChangeType(value, typeof(T));
                    return (T)result;
                }
                catch (Exception err)
                {
                    Debug.WriteLine(err.Message);
                    return default(T); 
                }
            }
        }

    }
}

Next is a couple of unit tests written in NUnit for this extension method. All tests passes.

using System;
using System.Reflection;
using Hemit.OpPlan.Common.DataContract;
using NUnit.Framework;  

namespace Hemit.OpPlan.Common.Test.Extensions
{
    
    [TestFixture] 
    public class ObjectExtensionsTest
    {

        [Test]
        [TestCase("4", typeof(int), 4)]
        [TestCase("true", typeof(bool), true)]
        [TestCase(null, typeof(bool), false)]
        [TestCase(null, typeof(Nullable<bool>), null)]
        [TestCase("true", typeof(Nullable<bool>), true)]
        [TestCase("FutureOperation", typeof(OperationStatusDataContract), OperationStatusDataContract.FutureOperation)]
        [TestCase("Postponed", typeof(OperationStatusDataContract), OperationStatusDataContract.Postponed)]
        public void ToReturnsExpected(object input, Type genericTypeArgument, object expected)
        {
            MethodInfo method = typeof(ObjectExtensions).GetMethod("To");
            MethodInfo genericMethod = method.MakeGenericMethod(new Type[] { genericTypeArgument });
            object actual = genericMethod.Invoke(input, new object[]{ input });
            Assert.AreEqual(actual, expected); 
        }

        [Test] 
        public void ToReturnsExpectedWithNullableBoolean()
        {
            int? inputValue = new Nullable<int>(3);
            int actual = ((int?)inputValue).To<int>(); 
            Assert.AreEqual(actual, 3); 
        }

    }

}


The code above shows how one can call a generic method, shown in the unit test. Multiple test cases are passed into this unit test method. As is visible to the reader, the class ObjectExtensions contains the method To, which considers a conversion of an object to a designated type. The conversion itself must of course be valid, in addition one should check that the value implements IConvertible or similar interface. I have kept the code rather short and will eloborate the code if I see thare are conversions that fail, which should work.

Wednesday, 23 April 2014

Using LinqKit and PredicateBuilder to create reusable predicates or filters in Entity Framework

If one has worked with Entity Framework for a while, sooner or later it becomes clear that refactoring logic into separate methods is hard, because Entity Framework must transform the code one writes in Linq to Entities into SQL. Therefore, extracting logic in EF into method calls will compile, but give a runtime error. The solution is to use the library LinqKit, created by brothers Joe and Ben Albahiri. It is available as a Nuget package: install-package LinqKit or at the following web site: LinqKit

The following simple example shows how it is possible to create a reusable predicate separated into a method of its own and call this method in Linq to entities code. Make note of the use of the AsExpandable() extension method that transforms the DbSet into an IQueryable by returning a wrapper that allows this. The code is run inside LinqPad. Make note that LinqPad has got inherent support for PredicateBuilder, but the LinqKit DLL was added as a reference. Also the namespace imports added where: System.Linq, System.Linq.Expressions and LinqKit. Press F4 to set up the additional references and imports in Linqpad.

public Expression<Func<Patient, bool>> InterestingPatient(params string[] keywords){
 var predicate = PredicateBuilder.False<Patient>(); 
 foreach (string keyword in keywords){
  string temp = keyword; 
  predicate = predicate.Or(p => p.Name.Contains(temp)); 
 }
 return predicate; 
}

void Main()
{
   Patients.AsExpandable().Where(InterestingPatient("Olsen", "Nilsen")).Dump(); 
}




The following images shows the output. Make note that Patient here is a table in the context of my project. The data shown here is test data (not real pasients of course):

Wednesday, 5 March 2014

Entity Framework Code First Generic Entity store operations

This article will discuss how generic entity store operations towards a data context can be used with EF Code First. This is tested with EF 6. First, define an interface with the often used generic entity store operations:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{

    public interface IRepo : IDisposable
    {

        T Insert<T>(T item, bool saveNow) where T : class;

        T Update<T>(T item, bool saveNow) where T : class;

        T Delete<T>(T item, bool saveNow) where T : class;

        int Save(); 

    }

}

Then implement this interface:

using System.Data.Entity;

namespace TestEFCodeFirst1
{
    
    public class Repo<TContext> : IRepo
        where TContext : DbContext, new()
    {

        public Repo()
        {
            Context = new TContext(); 
        }

        protected TContext Context { get; private set; }

        #region IRepo Members

        public T Insert<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Added;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Update<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Modified;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Delete<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Deleted;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public void Dispose()
        {
            Context.Dispose(); 
        }

        #endregion

        #region IRepo Members


        public int Save()
        {
            return Context.SaveChanges(); 
        }

        #endregion
    }

}

Next, create a simple DbContext to test out:

  
  public class DemoDbContext : DbContext
    {


        public DemoDbContext() : base("EFCodeFirstDemoDb1")
        {
            
            
        }


        public DbSet<Student> Students { get; private set; }

    }


An example of using this db context in a derived repo class is shown next:

public class DemoRepo : Repo<DemoDbContext>
{

}

The next code shows how to use this extension method:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{
    class Program
    {
        static void Main(string[] args)
        {

            Database.SetInitializer(new Init()); 

            using (var repo = new DemoRepo())
            {
                repo.Insert(new Student { Name = "Hardy", DateAdded = DateTime.Now,
                LastMod = DateTime.Now}, true);

                repo.Insert(new Student
                {
                    Name = "Joey",
                    DateAdded = DateTime.Now,
                    LastMod = DateTime.Now
                }, true);                

            }
        }

    }
}


To automatically patch your database do this:

In package-manager console type: Enable-Migrations In the configuration class, set AutomaticMigrationsEnabled to true.

namespace TestEFCodeFirst1.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<TestEFCodeFirst1.DemoDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(TestEFCodeFirst1.DemoDbContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}


Add an Init class:

using TestEFCodeFirst1.Migrations;

namespace TestEFCodeFirst1
{

    internal class Init : System.Data.Entity.MigrateDatabaseToLatestVersion
    {

    }
}

This explains what is done in the line further up: Database.SetInitializer(new Init());

Tuesday, 18 February 2014

Performing slow work outside the WPF UI thread and updating the WPF GUI afterwards

Developers using WPF are very familiar with the problem of doing slow work on the UI thread and trying to update the GUI thread afterwards. This is not only a problem in WPF, but also in Windows Forms and even web applications. If the UI thread is being kept busy with a heavy, synchronous calculation, other work such as resizing the window and even repainting the UI will suffer and this results in a non-responsive GUI that the user cannot work with. The solution is to do work in another thread or threads and update the GUI afterwards. To make this easier, I list up an extension method below to do this. The extension method is an extension method on the dispatcher, which will usually be this.Dispatcher in code behind or Dispatcher.CurrentDispatcher in MVVM scenarios and the user must supply the function that will return the thread work return a type T (this can be either an object or a list of objects for example) and also a gui update method that receives an object of type T that the thread work method calculated. The gui update method will usually specify what shall be performed in the GUI or in the ViewModel in MVVM scenarios, while the thread work method specifies first will specify how the object of type T is retrieved. It should be possible to use this extension method both in code-behind and MVVM scenarios.

public static class DispatcherUtil
    {

        public static void AsyncWorkAndUIThreadUpdate<T>(this Dispatcher currentDispatcher, Func<T> threadWork, Action<T> guiUpdate)
        {
            ThreadPool.QueueUserWorkItem(delegate(object state)
            {
                T resultAfterThreadWork = threadWork(); 
                currentDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action<T>(delegate(T result){
                    guiUpdate(resultAfterThreadWork);
                }), resultAfterThreadWork); 

            }); 
        }

    }

Next, an example of using this:

  private void Button_Click(object sender, RoutedEventArgs e)
        {

            this.Dispatcher.AsyncWorkAndUIThreadUpdate(() => FooService.GetSomeFooData(),
                s => btnFoo.Content = s); 

        }

The FooService is very simple and simulates a resource intensive calculation that takes about 5 seconds:

public static class FooService
    {

        public static string GetSomeFooData()
        {
            Thread.Sleep(5000);
            return "Hello world! "  + DateTime.Now.ToString(); 
        }

    }

I use ThreadPool.QueueUserWorkItem here. Of course this is a very simple example, and in complex applications one needs to watch out for state problems in the UI. When it is not sure when the calculation is performed, you should perhaps consider to avoid refreshing the UI if the UI has changed, especially in more complex MVVM component based WPF User Interfaces, based on for example Prism. At the same time, locking up the UI is not good either. I have only tested the code above in a simple scenario, but expect it to work also with more complex WPF UI. There are two golden rules when it comes to threading in WPF: 1. Never access UI elements from another thread than the UI thread 2. Do not do slow work on the UI thread but in another thread Most difficulties doing off thread async work in WPF comes to updating the UI after the calcuations are done in the other thread(s). With this extension method, hopefully WPF developers will find it easier.

Traversing paged results using Massive data access wrapper

Massive, a library created by brilliant developer Rob Conery and Jon Skeet's frequent humorous side-kick, has got a lot of nice features. Its best features are ease of use and dynamic appeal. It is also fast and lightweight. After testing Massive, I wanted to create an extension method to traverse paged results returned from Massive. The code below is tested against the AdventureWorks2012 database. First off, install Massive. I have created a simple Console Project to test this out and then use the Library Package Manager to install Massive:

Install-Package Massive -Version 1.1.0 

Remember to add the -Version switch above. Then install the AdventureWorks 2012 database here: http://msftdbprodsamples.codeplex.com/releases/view/55330 Add a connection string against the Adventure Works 2012 database after installing this on your developer PC. Use Data Explorer or Server Explorer in Visual Studio. Rename the connection string in your app.config or web.config to "adventureworks2012". Define a model entity for the Production.Product table next:

    public class Products : DynamicModel
    {
        public Products()
            : base("adventureworks2012", "Production.Product", "productid")
        {

        }
    }

To add a table entity in Massive, specify the connection string name, then the name of the table and then the primary keys. If you omit the name of the connection string, the first connection string found is used. Next, the code for the extension method to work against this DynamicModel inherited class and other inherited classes from DynamicModel:

     public static class MassiveExtensions
    {

        public static void MassivePagedAction(this DynamicModel massiveObject, int pageSize = 20, int startPageIndex = 1, 
            int endPageIndex = -1, Action<int, dynamic> pageAction = null, Action<dynamic> itemAction = null)
        {

            var pages = new Dictionary<int, dynamic>(); 
            var firstPage = massiveObject.Paged(currentPage: startPageIndex, pageSize: pageSize);
            pages.Add(startPageIndex, firstPage);
            int endIndex = endPageIndex == -1 ? firstPage.TotalPages : Math.Min(firstPage.TotalPages, endPageIndex); 
            
            for (int currentPageIndex = startPageIndex + 1; currentPageIndex <= endIndex; currentPageIndex++)
            {
                var currentPage = massiveObject.Paged(currentPage: currentPageIndex, pageSize: pageSize);
                pages.Add(currentPageIndex, currentPage); 
            }

            foreach (var keyValuePair in pages)
            {
                if (pageAction != null)
                    pageAction(keyValuePair.Key, keyValuePair.Value);
                foreach (var item in keyValuePair.Value.Items)
                {
                    if (itemAction != null)
                        itemAction(item); 
                }
            }

        }

    }


The extension method puts the paged results in a dictionary, where the keys are the page index and the value is the dynamic object that Massive returns, containing the paged data. There are numerous optional parameters to this extension method. The page size is default set to 20, if not specified. The start page index is 1, which is actually the default value. Rob Conery should perhaps have chosen the page index to be 0-based, as this is the standard in C#, but querying for page index 0 will give empty results. The end page index is default set to -1. This means that all pages will be returned, until there are not more pages. If you set the endPageIndex to a value less than firstPage.TotalPages inside the extension method, i.e. the actual total pages in the database, only pages up to the endPageIndex is returned. To get a single page, pass in a start and end index that differs with 1 (where end index has a value of one larger than start index). It is also possible to pass in page actions and item actions here. They default to null, but obviously at least an item action is desired to be set. A variant of the method above to allow a Func to be passed in to for example return results to the caller is interesting. Using the extension method above is shown next:

//GET PAGES RESULTS OF THE PRODUCTS TABLE USING A PAGE SIZE OF FIVE. GET ENTIRE TABLE.

            DynamicModel table = new Products();
          
            table.MassivePagedAction(pageSize:5,pageAction: (indx, page) => 
             Console.WriteLine("\nProducts in page # {0}:\n", indx), 
             itemAction: item => Console.WriteLine(item.Name)); 


//SAMPLE OUTPUT:


------ Test started: Assembly: TestMassive.exe ------


Products in page # 1:

Adjustable Race
Bearing Ball
BB Ball Bearing
Headset Ball Bearings
Blade

Products in page # 2:

LL Crankarm
ML Crankarm
HL Crankarm
Chainring Bolts
Chainring Nut

Products in page # 3:

..

//This resulted in 101 pages - There are 504 products in the AdventureWorks 2012 database (primarily mountain bikes and clothes+equipment)

Products in page # 101:

HL Bottom Bracket
Road-750 Black, 44
Road-750 Black, 48
Road-750 Black, 52

//Final page contains only four items as expected

To get a paged result and work with this paged result, another extension method can be used:

  public static Dictionary<int,List<ExpandoObject>> MassivePagedRetrieval(this DynamicModel massiveObject, int pageSize = 20, int startPageIndex = 1,
           int endPageIndex = -1)
        {

            var pages = new Dictionary<int, dynamic>();
            var pagedResult = new Dictionary<int, List<ExpandoObject>>(); 
            var firstPage = massiveObject.Paged(currentPage: startPageIndex, pageSize: pageSize);
            pages.Add(startPageIndex, firstPage);
            int endIndex = endPageIndex == -1 ? firstPage.TotalPages : Math.Min(firstPage.TotalPages, endPageIndex);

            for (int currentPageIndex = startPageIndex + 1; currentPageIndex <= endIndex; currentPageIndex++)
            {
                var currentPage = massiveObject.Paged(currentPage: currentPageIndex, pageSize: pageSize);
                pages.Add(currentPageIndex, currentPage);
            }

            foreach (var keyValuePair in pages)
            {
                List<ExpandoObject> items = new List<ExpandoObject>(); 
                foreach (var item in keyValuePair.Value.Items)
                {
                    items.Add(item); 
                }
                pagedResult[keyValuePair.Key] = items;
            }

            return pagedResult;
        }

To use this extension method, use:

     Dictionary<int, List<ExpandoObject>> pagedResult = table.MassivePagedRetrieval(pageSize: 10); 

The key is the page index again and a list of ExpandoObject objects are returned for each page (or key) in the dictionary. ExpandoObject is a dynamic object. To watch the resulting data in Visual Studio, use the debugger and choose Dynamic View when inspecting the result through debugging brekpoints in your code. This article has focused on paged data, as Massive often can be used to performed paged data retrieval in for example ASP.NET MVC-based solutions, but also other solutions can use this data access wrapper. The requirement is .NET 4.0 as System.Dynamics is the library which is used. Massive supports most features as more complex Object Relational Wrappers, such as Entity Framework. Its better speed and ease of use should be tempting. Rob Conery has got additonal information here: Massive Github page There is a trade off with Massive too, its dynamic nature is also its Achilles heel. If you rename fields in the database, you most likely must also update your code and since it is dynamic, chances are that errors can occur and be detected in runtime, out in production. This is easier to avoid using strongly typing such that Entity Framework also. Sadly, Entity Framework and many other ORMs are also slow. The following code shows how it is possible to retrieve a result from two tables. As you can see, one has to pass in SQL to output data.

var productsWithCategories = 
table.Query("SELECT p.Name, pc.Name As CategoryName FROM Production.Product p INNER JOIN Production.ProductCategory pc ON p.ProductSubCategoryId = pc.ProductCategoryId");

foreach (var ppc in productsWithCategories)
{
 Console.WriteLine("Product Name: {0}, Product category name: {1}", ppc.Name, ppc.CategoryName);
}

//RESULTING OUTPUT: 

Product Name: Road-150 Red, 62, Product category name: Components
Product Name: Road-150 Red, 44, Product category name: Components
Product Name: Road-150 Red, 48, Product category name: Components
Product Name: Road-150 Red, 52, Product category name: Components

..

This results in a quick way to access the database, but also loosing Intellisense (auto completion), strongly static typing and compile type checking. When returning results from the database in a service, it is possible to return the data as ExpandoObjects as shown in the extension method MassivePagedRetrieval shown above. If one uses ASP.NET MVC, the Model can bind to this data. This results in fewer application layers and less coding, but at the same time a risk for those pesky runtime errors out in production. Massive is very quick and for web developers, this looks very promising. Using ElasticObject or similar techniques, the ExpandoObjects can be converted to either XML or better - JSON - and processed using jQuery and Javascript. If Massive catches on or some other, ligtweight ORM is preferred by developers remains to be seen. This is a moving field. What is sure, the days of heavy weight ORMs like Entity Framework will not be bright if not the performance catches up with these lighter ORM frameworks. At the same time, it is hard to say that it actually will result in shorter time to market (TTM) for developers, as they loose Intellisens and other good features such as Entity Framework supports. Test out Massive and see if it matches your needs. Use the extension methods above to get started with paged result retrieval, if they look interesting. Massive also supports of course inserts, updates and deletes. In addition, validations and callbacks can be put in the class that inherit from DynamicModel. Massive also has specialized functions such as the standard aggregation methods and convenience method such as Find that is defined in the DynamicModel. Lastly, Massive is heavily based on System.Dynamics assembly in .NET 4.0 and newer framework versions. DynamicModel inherits itself from System.Data.DynamicObject. Also bulk updates are supported in Massive.

Monday, 17 February 2014

Using ElasticObject to parse arbitrarily large XML documents into object graphs

ElasticObject is a great implementation of a DynamicObject, that allows the developer to work with an arbitrarily large XML document, using an object graph. The code below access the Norwegian Weather Forecast service Yr.no to get some forecast data for the location where I grew up in Norway, where a weather station nearby automatically collects meteorological data such as wind, temperature, pressure and wind direction, humidity and so on. The data is available among other ways as XML to download and ElasticObject can be used to handle the XML. When handling XML, it is possible to create an XSD from sample XML data and in for example Visual Studio create an XSD file through XML->Create Schema option in Visual Studio after opening the sample XML file. Using the Visual Studio Command line, it is possible to generate a class through the command:

xsd /classes myfile.xsd

This generates a file called myfile.cs, which will be a data contract.

The data contract generated can be used to deserialize the XML into an object. Often this is a preferred strategy, since one gets a strongly typed object (graph) to work with. ElasticObject is a dynamic object, and allows the developer to avoid having to generate a serialization class before deserializing the received XML. Sometimes, this also allows changes in the XML to occur without affecting the code. Often it is a limited part of the XML tree, which is the received XML the developer needs to retrieve for further processing. Also, not having to generate classes from the XML schema is also convenient. Still, the developer needs to refer more often to the XML to understand the structure of the object which is created. The Intellisense of ElasticObject is rather poor, so the developer needs to query the object graph using Immediate Window and query the object to find the right "path" to the information in the XML document. Similar techniques using System.Linq.Xml and XPath queries can be used. To start using ElasticObject, install first the NuGet package in Visual Studio. Type the following command in Package Manager Console.

PM> install-package AmazedSaint.ElasticObject
Installing 'AmazedSaint.ElasticObject 1.2.0'.
Successfully installed 'AmazedSaint.ElasticObject 1.2.0'.
Adding 'AmazedSaint.ElasticObject 1.2.0' to TestElasticObject.
Successfully added 'AmazedSaint.ElasticObject 1.2.0' to TestElasticObject.

The following code then illustrates the use:

using AmazedSaint.Elastic;
using System;
using System.IO;
using System.Net;
using System.Xml.Linq;

namespace TestElasticObject
{
    class Program
    {

        static void Main(string[] args)
        {
            var wc = new WebClient();
          
            using (StreamReader sr = new StreamReader(wc.OpenRead(@"http://www.yr.no/stad/Norge/Nord-Tr%C3%B8ndelag/Steinkjer/S%C3%B8ndre%20Egge/varsel.xml")))
            {
                var data = sr.ReadToEnd();
                IterateForecasts(data);          
            }

            Console.WriteLine("Press any key to continue ...");
            Console.ReadKey(); 

        }

        private static void IterateForecasts(string data)
        {
            dynamic weatherdata = XElement.Parse(data).ToElastic();
            foreach (var node in weatherdata.forecast.text.location[null])
            {
                Console.WriteLine(string.Format("Fra-Til: {0} - {1}", node.from, node.to)); 
                Console.WriteLine(~node.body);
                Console.WriteLine();
            }
        }

    }
}


The code above uses WebClient to download the target XML data, then uses a StreamReader to read the XML file into a string. Then using XElement and the ToElastic extension method in AmazedSaint.Elastic namespace, this is stored into a dynamic variable which can be worked on. One important gotcha here is how to drill down into the object graph of the ElasticObject, which I could not figure out following the documentation, since it only contained more simple examples but I found on StackOverFlow: To drill further down into the object graph than its immediate child node, type the path to the element which contains the data to work with using a dot separated syntax and in addition: use the null index to get to the child element which contains the data to process - for example to output. When traversing the child element in the foreach loop, its child elements will be stored into the loop variable node and then it is possible to get to the attributes of the node. To get the value inside the element, use the tilde (~) operator. ElasticObject implements some operators to make it easier to work with XML and object graphs. For example, to cast an ElasticObject to XML, the > operator can be used:

            dynamic store = new ElasticObject("Store");
            store.Name = "Acme Store";
            store.Location.Address = "West Avenue, Heaven Street Road, LA";
            store.Products.Count = 2;
            store.Owner.FirstName = "Jack";
            store.Owner.SecondName = "Reacher";
            store.Owner <<= "this is some internal content for owner";

            var p1 = store.Products.Product();
            p1.Name = "Acme Floor Cleaner";
            p1.Price = 20;

            var p2 = store.Products.Product();
            p2.Name = "Acme Bun";
            p2.Price = 22; 

            XElement el = store > FormatType.Xml; 
            System.Console.WriteLine(el.ToString());

The ElasticObject is defined dynamically and the <<= operator is used to set the value inside the property, which will be shown when converting the ElasticObject to XML. In addition, the code above shows how to create child elements, as the Products property contains two child Product objects, which will be Product XML elements. The < operator is used to "pipe" the object into an XElement variable, which is the converted XML object from the ElasticObject object graph. To convert the object from an XML document to an ElasticObject, the ToElastic() extension method can be used to convert the XML document or XElement variable into the ElasticObject - the object graph again. Using ElasticObject, it is possible to work with XML in object graphs and since it is dynamic, it is not necessary to create new types, such as serialization data contracts. ElasticObject source code is available on GitHub here: https://github.com/amazedsaint/ElasticObject
Its creator is Anoop Madhusudanan, AmazedSaint profile on GitHub. It originally was a project hosted on CodePlex. ElasticObject should be considered as an alternative when working with XML and object graphs. It is very tempting to avoid having to create new objects to work with the XML but work with a dynamic object that can be extended and changed. It should also be efficient. An alternative can be to use anonymous types, but why go the hard way when one can go the easy - elastic way?

IoC container example

This article will present an IoC container that can resolve concrete types via interfaces or instances recursively. It should not be used in production code without improved loop detection and error handling, but can in some scenarios be used if one needs a very simple (and fast) IoC container.

The code is heavily based on Jon Skeet's walkthrough of a IoC container ("IoC container on the fly").

First the code of the IoC container itself:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace TestComposedIoCContainer
{
    
    public class CompositionContainer
    {

        private readonly Dictionary<Type, Func<object>> providers = new Dictionary<Type, Func<object>>();

        private readonly object providersLocker = new object(); 


        public void Bind<TKey, TConcrete>() where TConcrete : TKey
        {
            lock (providersLocker)
            {
                providers[typeof(TKey)] = () => ResolveByType(typeof(TConcrete));
            }
        }

        public void Bind<T>(T instance)
        {
            lock (providersLocker)
            {
                providers[typeof(T)] = () => instance;
            }
        }

        private object ResolveByType(Type type)
        {
            var constructors = type.GetConstructors();
            if (constructors != null)
            {
                ConstructorInfo cInfo;
                cInfo = constructors.Count() == 1 ? constructors.Single() : 
                    constructors.Where(c => 
                    c.GetCustomAttributes(typeof(ImportConstructorAttribute), false).Length > 0).FirstOrDefault(); 
                if (cInfo == null)
                    throw new Exception(GetUsageMessage(type));
                var arguments = cInfo.GetParameters().Select(p => Resolve(p.ParameterType)).ToArray();
                return cInfo.Invoke(arguments);
            }
            else
            {
                var instanceField = type.GetField("Instance");
                if (instanceField != null)
                    return instanceField.GetValue(null);
                else
                    throw new Exception(GetUsageMessage(type));
            }
        }

        private static string GetUsageMessage(Type type)
        {
            return "Could not resolve a type implementing " + type.Name 
            + " - it must be registered through Bind to the composition container and either contain a single constructor or one constructor " 
            + "decorated with ImportContructor attribute or a field named Instance";
        }

        internal TKey Resolve<TKey>()
        {
            return (TKey)Resolve(typeof(TKey)); 
        }

        internal object Resolve(Type type)
        {
            Func<object> provider;
            if (providers.TryGetValue(type, out provider))
                return provider();
            else
                return ResolveByType(type);
        }

    }

}


The IoC container contains a dictionary which has got a Type as the Key, which is the usually either the interface or the concrete type to register through the Bind calls to the container, and a function expression that returns either an instance or resolves an instance through the container. When resolving a type, it can be multiple constructors in the class. I have extended Jon Skeet's code a bit, and by decorating the constructor by a ImportConstructor attribute, it is possible to specify which constructor is the constructor that should be the inversion of control constructor. Pass in all dependencies that must be resolved in that constructor. If the importing type or "part" to use a phrase from MEF, has no constructors that should be used, a field called "Instance" can be used. This is to support singleton patterns or similar. I have chosen to add locking when performing binds, to make this thread safe. Resolving instances is not made thread safe, as this can give very much locking. Usually a composition container is anyways set up in a single thread through registering bindings and then multiple threads will possibly access the IoC container. It is possible to put the CompositionContainer itself as a singleton, which is what one usually wants. I have added a generic singleton implementation in my blog that can be used to support this. The import constructor attribute is very simple:

using System;

namespace TestComposedIoCContainer
{
    
    public class ImportConstructorAttribute : Attribute
    {
    }
}

A unit test to display the use of this composition container, followed by the class definitions:

using NUnit.Framework;
using System;

namespace TestComposedIoCContainer
{
   
    [TestFixture]
    public class Program
    {

        [Test]
        public void MainTest()
        {
            var container = new CompositionContainer();
            container.Bind<ICalculator, Calculator>();
            container.Bind<IAdder, Adder>();
            container.Bind<IMultiplier, Multiplier>(); 

            var calculator = container.Resolve<ICalculator>();
            Console.WriteLine("Calculator resolved!");
            int resultAdd = calculator.Add(3, 5);
            Console.WriteLine("3 + 5 = {0}", resultAdd);

            int resultMult = calculator.Multiply(4, 8);
            Console.WriteLine("4 * 8 = {0}", resultMult);
        }

        public static void Main(string[] args)
        {

        }

    }

}


//CLASS DEFINITIONS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestComposedIoCContainer
{
    
    public class Calculator : ICalculator
    {

        private IAdder adder;

        private IMultiplier multiplier;

        public Calculator()
        {

        }

        [ImportConstructor]
        public Calculator(IAdder adder, IMultiplier multiplier)
        {
            this.adder = adder;
            this.multiplier = multiplier; 
        }

        public int Add(int x, int y)
        {
            return adder.Add(x, y); 
        }

        public int Multiply(int x, int y)
        {
            return multiplier.Multiply(x, y); 
        }

    }


namespace TestComposedIoCContainer
{
    
    public interface ICalculator
    {

        int Add(int x, int y);

        int Multiply(int x, int y); 

    }

}


}


namespace TestComposedIoCContainer
{
    
    public class Adder : IAdder
    {

        public int Add(int x, int y)
        {
            return x + y; 
        }
    }

}


namespace TestComposedIoCContainer
{
    
    public interface IAdder
    {

        int Add(int x, int y);

    }

}


namespace TestComposedIoCContainer
{
    
    public interface IMultiplier
    {

        int Multiply(int x, int y);

    }

}


namespace TestComposedIoCContainer
{
    
    public class Multiplier : IMultiplier
    {

        public Multiplier()
        {

        }

        public int Multiply(int x, int y)
        {
            return x * y;            
        }

    }

}

//RESULT OF RUNNING NUNIT UNIT TEST ABOVE: 

------ Test started: Assembly: TestComposedIoCContainer.exe ------

Calculator resolved!
3 + 5 = 8
4 * 8 = 32

1 passed, 0 failed, 0 skipped, took 0,46 seconds (NUnit 2.6.2).



The code above should only be used for simple IoC scenarios. The IoC container uses very much reflection, which should not be consider the quickest way of resolving objects. The IoC container code can though resolve arbitrarily complex object graphs, when the registering of binds are done correctly, however there is a weakness here - the container does not do loop detection very good. For example, if a "part" or "component" of the composition container imports another parts and this part again resolves that part or some other recursive relation, looping will start to occur. But at the same time - many IoC frameworks are poor at detecting such errors anyways and will also give infinite recursion here. If you have simple needs for IoC resolution, the code above can be used in simple scenarios but most production code should instead choose among the many professional IoC frameworks out there.

Saturday, 15 February 2014

Grunt.Js presentasjon

Grunt.js presentasjon

Grunt.Js presentasjon kan lastes ned her:

http://www.aurstad.info/GruntJs.pdf [PDF]

Note to my English readers, the GruntJs presentation is written in Norwegian.

Saturday, 4 January 2014

Compressing a byte array in C# with GZipStream

In .NET 4.0 or later versions, it is possible to compress a byte array with GZipStream and therefore the GZip algorithm. The GZipStream can be outputted to an array or a file. The code below shows a wrapper class for compressing a byte array, decompressing it and a unit test that reads all the bytes in text file, then compresses it, decompresses it and checks that the decompressed byte array has the same byte values as the bytes read from the text file. Compression and decompression code next:

using System;
using System.IO;
using System.IO.Compression;

namespace TestCompression
{
    
    /// 
    /// Compresses or decompresses byte arrays using GZipStream
    /// 
    public static class ByteArrayCompressionUtility
    {

        private static int BUFFER_SIZE = 64*1024; //64kB

        public static byte[] Compress(byte[] inputData)
        {
            if (inputData == null)
                throw new ArgumentNullException("inputData must be non-null");

            using (var compressIntoMs = new MemoryStream())
            {
                using (var gzs = new BufferedStream(new GZipStream(compressIntoMs, 
                 CompressionMode.Compress), BUFFER_SIZE))
                {
                    gzs.Write(inputData, 0, inputData.Length);
                }
                return compressIntoMs.ToArray(); 
            }
        }

        public static byte[] Decompress(byte[] inputData)
        {
            if (inputData == null)
                throw new ArgumentNullException("inputData must be non-null");

            using (var compressedMs = new MemoryStream(inputData))
            {
                using (var decompressedMs = new MemoryStream())
                {
                    using (var gzs = new BufferedStream(new GZipStream(compressedMs, 
                     CompressionMode.Decompress), BUFFER_SIZE))
                    {
                        gzs.CopyTo(decompressedMs);
                    }
                    return decompressedMs.ToArray(); 
                }
            }
        }

        //private static void Pump(Stream input, Stream output)
        //{
        //    byte[] bytes = new byte[4096];
        //    int n;
        //    while ((n = input.Read(bytes, 0, bytes.Length)) != 0)
        //    {
        //        output.Write(bytes, 0, n); 
        //    }
        //}
        


    }

}


In the code, memorystreams are used and the ToArray() method is used to generate byte arrays. The GZipStream can have a compression mode of either Compress or Decompress. The GZipStream in the compress and decompress methods are wrapped with BufferedStream with a buffer size of 64kB. This is done to be able to handle larger files. I have tested this code in a unit test with a lorem ipsum generated text file about 5,5 MB. The unit test is shown next:

using System;
using NUnit.Framework;
using System.Text;
using System.IO;
using System.Linq;


namespace TestCompression.Test
{
    [TestFixture]
    public class UnitTest1
    {

        [Test]
        public void CompressAndUncompressString()
        {
            byte[] inputData = File.ReadAllBytes("Lorem1.txt");
            byte[] compressedData = ByteArrayCompressionUtility.Compress(inputData);
            byte[] decompressedData = ByteArrayCompressionUtility.Decompress(compressedData);

            Assert.IsNotEmpty(inputData);
            Assert.IsNotEmpty(decompressedData);
            Assert.IsTrue(inputData.SequenceEqual(decompressedData));

            Console.WriteLine("Compressed size: {0:F2}%", 
             100 * ((double)compressedData.Length / (double)decompressedData.Length));

            //string outputString = Encoding.UTF8.GetString(decompressedData);

        }

    }
}


Output of this unit test is shown next:

------ Test started: Assembly: TestCompression.Test.dll ------

Compressed size: 28,74%

1 passed, 0 failed, 0 skipped, took 18,87 seconds (NUnit 2.6.2).



To generate a lorem ipsum text file, you can use a lorep ipsum generator here: http://loripsum.net

Wednesday, 1 January 2014

RandomNumberGenerator in C#

To generate random numbers in C#, it is possible to use the class RandomNumberGenerator in System.Security.Cryptography namespace in .NET. This class can be easier to use with a simple wrapper class. The wrapper class provided here returns either an integer or an unsigned integer. The "randomness" is better in this class than in the default Random generator of .NET, the Random class. This class will for example emit the same random values for two instances instantiated at almost the same time of the Random class. The wrapper class looks like this:

 public static class RandomGenerator
    {

        private static readonly RandomNumberGenerator generator;

        static RandomGenerator()
        {
            generator = RandomNumberGenerator.Create();
        }

        public static int GetNext()
        {
            byte[] rndArray = new byte[4];
            generator.GetBytes(rndArray);
            return BitConverter.ToInt32(rndArray, 0);
        }

        public static uint GetNextUnsigned()
        {
            byte[] rndArray = new byte[4];
            generator.GetBytes(rndArray);
            return BitConverter.ToUInt32(rndArray, 0);
        }



    }

The class is in fact a static class with a static RandomNumberGenerator instance created in the static constructor. The methods to create a new random number uses the GetBytes method to fill a four byte array. We could of course generate longer arrays and create for example 64-bits integers, but here just a four byte array is used. Either an integer or unsigned integer is returned by the two respective methods for this. I have not bothered to refactor this simple class. The BitConverter class converts the byte array to int or unsigned int (32-bits) starting at index 0. We could also return other datatypes here than just integers. Simple unit test:

 [TestFixture]
    public class UnitTest1
    {

        [Test]
        public void GetNextInteger()
        {
            int random = RandomGenerator.GetNext();
            Debug.WriteLine(random);
        }

        [Test]
        public void GetNextUInteger()
        {
            uint random = RandomGenerator.GetNextUnsigned();
            Debug.WriteLine(random);
        }

    }

Sample output:

------ Test started: Assembly: TestRandomNumberGeneratorTest.dll ------

-1821995826

1013025195

2 passed, 0 failed, 0 skipped, took 0,42 seconds (NUnit 2.6.2).


If you would like random numbers in a specified range, for example 0 to 99, you could take the integer and do a modulo 100 operation, e.g RandomGenerator.GetNextUnsigned() % 100. Of course, this is tied to the desired range you want. If a range between for example -20 and 20 is desired, you could for example do something like: -20 + (RandomGenerator.GetNextUnsigned() % 41). The bottom line is that you should not entrust the randomness of System.Random class but use the RandomNumberGenerator class in System.Security.Cryptography if you want to generate random integers, signed or unsigned that exhibit more distributed randomness than the pseudorandomness of System.Random.

Thursday, 24 October 2013

Using Snoop and PowerShell to interrogate View Models in WPF applications

It is possible to use Snoop to interrogate View Models in WPF applications. If you first install Snoop, check that you run Snoop as an administrator, if you cannot attach to the process which is your WPF application. Start snooping the application, then move to the tab Powershell. Use Ctrl+Shift and click on the visual or ui element you want to inspect in the GUI. You will see a pink border around the ui element or visual and this will then be possible to inspect further. Go to the PowerShell tab and start interrogating the object. In the MVVM WPF application at my work, we can see the view model in the property DataContext.ViewModel. It is possible to further drill down to properties in the ViewModel quite easily. Example follows, I have selected a RadGridView in my application and select the Visual property, then look at the DataContext of the Visual, drill down further to the ModelCollection property, which in this particular example is a property of the data context object of which the selected visual is data bound to. This object contains a property of type ObservableCollection which has got some custom object inside. The collection object is then piped to the Select operator in Powershell and this Select operator projects the properties of each object in the ModelCollection, in this particular case I select OperationId, OperatingDate and OperationStatus. This is then further piped to Format-Table which is used with the argument -autoresize. The resulting selector is then:

$selected.Visual.DataContext.ModelCollection | Select OperationId, OperatingDate, OperationStatus | Format-Table -autosize

OperationId OperatingDate       OperationStatus
----------- -------------       ---------------
       2076                              Urgent
         70                              Urgent
       2162 23.10.2013 00:00:00       Operation
       2165 23.10.2013 00:00:00       Operation
       2196 23.10.2013 00:00:00       Operation
       2197 23.10.2013 00:00:00       Operation
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
          0 23.10.2013 00:00:00            None
       1913                              Urgent
       2192 23.10.2013 00:00:00       Operation
       2193 23.10.2013 00:00:00       Operation
       2194 23.10.2013 00:00:00       Operation
       2013 23.10.2013 00:00:00       Operation
       2195 23.10.2013 00:00:00       Operation
       2161 23.10.2013 00:00:00       Operation


It could be possible to pipe this further to the Export-Csv Powershell cmdlet and you can have Excel launch the resulting .csv file. This shows how SnoopWpf can be used to do powerful runtime analysis and inspection of WPF applications and also support Powershell operators. Both technical testers and WPF developers will find this useful. To get started, install Snoop Wpf created by the brilliant developer Cory Plotts and can be downloaded from here: Snoop WPF

Friday, 26 July 2013

Creating a simple autocomplete control with Bootstrap for with a remote JSON service

I have worked a bit with the Twitter Bootstrap javascript library / framework and testet out the TypeAhead control. I could not find a complete example of how to get the autocomplete items from a remote JSON service, so I testet it out myself. Let's first define a web service (ASP.NET) which will return the list of sovereign states in the world:
//using System;
//using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;

namespace TestBootstrapCss
{
    /// <summary>
    /// Summary description for CountryService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class CountryService : System.Web.Services.WebService
    {

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Country[] GetCountries(string query)
        {
            if (cachedCountryList == null)
                cachedCountryList = GetCountryList();

            var result = cachedCountryList.Where(c => c.Name.StartsWith(query, System.StringComparison.CurrentCultureIgnoreCase)).ToArray();
            return result;
        }

        public class Country
        {
            public int Id { get; set; }

            public string Name { get; set; }

            public int Population { get; set; }

            public double WorldPercentage { get; set; }

        }

        private static Country[] cachedCountryList = null; 

        public Country[] GetCountryList()
        {
            return new Country[] {
                new Country { Id =1,Name = "China",Population = 1354040000 ,WorldPercentage = 19.07 },
                new Country { Id =2,Name = "India",Population = 1210569573 ,WorldPercentage = 17.05 },
                new Country { Id =3,Name = "United States",Population = 316318000 ,WorldPercentage = 4.45 },
                new Country { Id =4,Name = "Indonesia",Population = 237641326 ,WorldPercentage = 3.35 },
                new Country { Id =5,Name = "Brazil",Population = 193946886 ,WorldPercentage = 2.73 },
                new Country { Id =6,Name = "Pakistan",Population = 183766000 ,WorldPercentage = 2.59 },
                new Country { Id =7,Name = "Nigeria",Population = 173615000 ,WorldPercentage = 2.45 },
                new Country { Id =8,Name = "Bangladesh",Population = 152518015 ,WorldPercentage = 2.15 },
                new Country { Id =9,Name = "Russia",Population = 143400000 ,WorldPercentage = 2.02 },
                new Country { Id =10,Name = "Japan",Population = 127350000 ,WorldPercentage = 1.79 },
                new Country { Id =11,Name = "Mexico",Population = 118419000 ,WorldPercentage = 1.67 },
                new Country { Id =12,Name = "Philippines",Population = 98100000 ,WorldPercentage = 1.38 },
                new Country { Id =13,Name = "Vietnam",Population = 88780000 ,WorldPercentage = 1.25 },
                new Country { Id =14,Name = "Ethiopia",Population = 86613986 ,WorldPercentage = 1.22 },
                new Country { Id =15,Name = "Egypt",Population = 83661000 ,WorldPercentage = 1.18 },
                new Country { Id =16,Name = "Germany",Population = 80493000 ,WorldPercentage = 1.13 },
                new Country { Id =17,Name = "Iran",Population = 76768000 ,WorldPercentage = 1.08 },
                new Country { Id =18,Name = "Turkey",Population = 75627384 ,WorldPercentage = 1.07 },
                new Country { Id =19,Name = "Democratic Republic of the Congo",Population = 67514000 ,WorldPercentage = 0.95 },
                new Country { Id =20,Name = "Thailand",Population = 65926261 ,WorldPercentage = 0.93 },
                new Country { Id =21,Name = "France[9]",Population = 65684000 ,WorldPercentage = 0.92 },
                new Country { Id =22,Name = "United Kingdom",Population = 63181775 ,WorldPercentage = 0.89 },
                new Country { Id =23,Name = "Italy",Population = 59704082 ,WorldPercentage = 0.84 },
                new Country { Id =24,Name = "Myanmar",Population = 53259000 ,WorldPercentage = 0.75 },
                new Country { Id =25,Name = "South Africa",Population = 52981991 ,WorldPercentage = 0.75 },
                new Country { Id =26,Name = "South Korea",Population = 50219669 ,WorldPercentage = 0.71 },
                new Country { Id =27,Name = "Colombia",Population = 47159000 ,WorldPercentage = 0.66 },
                new Country { Id =28,Name = "Spain",Population = 47059533 ,WorldPercentage = 0.66 },
                new Country { Id =29,Name = "Ukraine",Population = 45495252 ,WorldPercentage = 0.64 },
                new Country { Id =30,Name = "Tanzania",Population = 44928923 ,WorldPercentage = 0.63 },
                new Country { Id =31,Name = "Kenya",Population = 44354000 ,WorldPercentage = 0.62 },
                new Country { Id =32,Name = "Argentina",Population = 40117096 ,WorldPercentage = 0.57 },
                new Country { Id =33,Name = "Poland",Population = 38533299 ,WorldPercentage = 0.54 },
                new Country { Id =34,Name = "Sudan",Population = 37964000 ,WorldPercentage = 0.53 },
                new Country { Id =35,Name = "Algeria",Population = 37900000 ,WorldPercentage = 0.53 },
                new Country { Id =36,Name = "Canada",Population = 35141542 ,WorldPercentage = 0.49 },
                new Country { Id =37,Name = "Uganda",Population = 34131400 ,WorldPercentage = 0.48 },
                new Country { Id =38,Name = "Iraq",Population = 33330000 ,WorldPercentage = 0.47 },
                new Country { Id =39,Name = "Morocco",Population = 32973200 ,WorldPercentage = 0.46 },
                new Country { Id =40,Name = "Peru",Population = 30475144 ,WorldPercentage = 0.43 },
                new Country { Id =41,Name = "Malaysia",Population = 29747000 ,WorldPercentage = 0.42 },
                new Country { Id =42,Name = "Uzbekistan",Population = 29559100 ,WorldPercentage = 0.42 },
                new Country { Id =43,Name = "Saudi Arabia",Population = 29195895 ,WorldPercentage = 0.41 },
                new Country { Id =44,Name = "Venezuela",Population = 28946101 ,WorldPercentage = 0.41 },
                new Country { Id =45,Name = "Nepal",Population = 26494504 ,WorldPercentage = 0.37 },
                new Country { Id =46,Name = "Afghanistan",Population = 25500100 ,WorldPercentage = 0.36 },
                new Country { Id =47,Name = "North Korea",Population = 24895000 ,WorldPercentage = 0.35 },
                new Country { Id =48,Name = "Ghana",Population = 24658823 ,WorldPercentage = 0.35 },
                new Country { Id =49,Name = "Yemen",Population = 24527000 ,WorldPercentage = 0.35 },
                new Country { Id =50,Name = "Mozambique",Population = 24366112 ,WorldPercentage = 0.34 },
                new Country { Id =51,Name = "Taiwan[10]",Population = 23340136 ,WorldPercentage = 0.33 },
                new Country { Id =52,Name = "Ivory Coast",Population = 23202000 ,WorldPercentage = 0.33 },
                new Country { Id =53,Name = "Australia",Population = 23096296 ,WorldPercentage = 0.33 },
                new Country { Id =54,Name = "Syria",Population = 21377000 ,WorldPercentage = 0.3 },
                new Country { Id =55,Name = "Madagascar",Population = 20696070 ,WorldPercentage = 0.29 },
                new Country { Id =56,Name = "Angola",Population = 20609294 ,WorldPercentage = 0.29 },
                new Country { Id =57,Name = "Cameroon",Population = 20386799 ,WorldPercentage = 0.29 },
                new Country { Id =58,Name = "Sri Lanka",Population = 20277597 ,WorldPercentage = 0.29 },
                new Country { Id =59,Name = "Romania",Population = 20121641 ,WorldPercentage = 0.28 },
                new Country { Id =60,Name = "Burkina Faso",Population = 17322796 ,WorldPercentage = 0.24 },
                new Country { Id =61,Name = "Niger",Population = 17129076 ,WorldPercentage = 0.24 },
                new Country { Id =62,Name = "Kazakhstan",Population = 17010000 ,WorldPercentage = 0.24 },
                new Country { Id =63,Name = "Netherlands",Population = 16793700 ,WorldPercentage = 0.24 },
                new Country { Id =64,Name = "Chile",Population = 16634603 ,WorldPercentage = 0.23 },
                new Country { Id =65,Name = "Ecuador",Population = 15535800 ,WorldPercentage = 0.22 },
                new Country { Id =66,Name = "Guatemala",Population = 15438384 ,WorldPercentage = 0.22 },
                new Country { Id =67,Name = "Mali",Population = 15302000 ,WorldPercentage = 0.22 },
                new Country { Id =68,Name = "Cambodia",Population = 15135000 ,WorldPercentage = 0.21 },
                new Country { Id =69,Name = "Malawi",Population = 14388600 ,WorldPercentage = 0.2 },
                new Country { Id =70,Name = "Senegal",Population = 13567338 ,WorldPercentage = 0.19 },
                new Country { Id =71,Name = "Zambia",Population = 13092666 ,WorldPercentage = 0.18 },
                new Country { Id =72,Name = "Zimbabwe",Population = 12973808 ,WorldPercentage = 0.18 },
                new Country { Id =73,Name = "Chad",Population = 12825000 ,WorldPercentage = 0.18 },
                new Country { Id =74,Name = "South Sudan",Population = 11296000 ,WorldPercentage = 0.16 },
                new Country { Id =75,Name = "Cuba",Population = 11163934 ,WorldPercentage = 0.16 },
                new Country { Id =76,Name = "Belgium",Population = 11156136 ,WorldPercentage = 0.16 },
                new Country { Id =77,Name = "Guinea",Population = 10824200 ,WorldPercentage = 0.15 },
                new Country { Id =78,Name = "Greece",Population = 10815197 ,WorldPercentage = 0.15 },
                new Country { Id =79,Name = "Tunisia",Population = 10777500 ,WorldPercentage = 0.15 },
                new Country { Id =80,Name = "Portugal",Population = 10562178 ,WorldPercentage = 0.15 },
                new Country { Id =81,Name = "Rwanda",Population = 10537222 ,WorldPercentage = 0.15 },
                new Country { Id =82,Name = "Czech Republic",Population = 10512800 ,WorldPercentage = 0.15 },
                new Country { Id =83,Name = "Somalia[11]",Population = 10496000 ,WorldPercentage = 0.15 },
                new Country { Id =84,Name = "Haiti",Population = 10413211 ,WorldPercentage = 0.15 },
                new Country { Id =85,Name = "Bolivia",Population = 10389913 ,WorldPercentage = 0.15 },
                new Country { Id =86,Name = "Benin",Population = 10323000 ,WorldPercentage = 0.15 },
                new Country { Id =87,Name = "Burundi",Population = 10163000 ,WorldPercentage = 0.14 },
                new Country { Id =88,Name = "Hungary",Population = 9906000 ,WorldPercentage = 0.14 },
                new Country { Id =89,Name = "Sweden",Population = 9588569 ,WorldPercentage = 0.14 },
                new Country { Id =90,Name = "Belarus",Population = 9458700 ,WorldPercentage = 0.13 },
                new Country { Id =91,Name = "Dominican Republic",Population = 9445281 ,WorldPercentage = 0.13 },
                new Country { Id =92,Name = "Azerbaijan",Population = 9235100 ,WorldPercentage = 0.13 },
                new Country { Id =93,Name = "Austria",Population = 8464554 ,WorldPercentage = 0.12 },
                new Country { Id =94,Name = "Honduras",Population = 8385072 ,WorldPercentage = 0.12 },
                new Country { Id =95,Name = "United Arab Emirates",Population = 8264070 ,WorldPercentage = 0.12 },
                new Country { Id =96,Name = "Switzerland",Population = 8058100 ,WorldPercentage = 0.11 },
                new Country { Id =97,Name = "Israel",Population = 8034900 ,WorldPercentage = 0.11 },
                new Country { Id =98,Name = "Tajikistan",Population = 8000000 ,WorldPercentage = 0.11 },
                new Country { Id =99,Name = "Bulgaria",Population = 7282041 ,WorldPercentage = 0.1 },
                new Country { Id =100,Name = "Serbia[12]",Population = 7241295 ,WorldPercentage = 0.1 },
                new Country { Id =101,Name = "Hong Kong (China)",Population = 7173900 ,WorldPercentage = 0.1 },
                new Country { Id =102,Name = "Papua New Guinea",Population = 7059653 ,WorldPercentage = 0.099 },
                new Country { Id =103,Name = "Paraguay",Population = 6672631 ,WorldPercentage = 0.094 },
                new Country { Id =104,Name = "Laos",Population = 6580800 ,WorldPercentage = 0.093 },
                new Country { Id =105,Name = "Jordan",Population = 6467500 ,WorldPercentage = 0.09 },
                new Country { Id =106,Name = "Eritrea",Population = 6333000 ,WorldPercentage = 0.089 },
                new Country { Id =107,Name = "Libya",Population = 6202000 ,WorldPercentage = 0.087 },
                new Country { Id =108,Name = "Togo",Population = 6191155 ,WorldPercentage = 0.087 },
                new Country { Id =109,Name = "El Salvador",Population = 6183000 ,WorldPercentage = 0.087 },
                new Country { Id =110,Name = "Sierra Leone",Population = 6092000 ,WorldPercentage = 0.086 },
                new Country { Id =111,Name = "Nicaragua",Population = 6071045 ,WorldPercentage = 0.086 },
                new Country { Id =112,Name = "Denmark",Population = 5605836 ,WorldPercentage = 0.079 },
                new Country { Id =113,Name = "Kyrgyzstan",Population = 5551900 ,WorldPercentage = 0.078 },
                new Country { Id =114,Name = "Finland",Population = 5434357 ,WorldPercentage = 0.077 },
                new Country { Id =115,Name = "Slovakia",Population = 5410728 ,WorldPercentage = 0.076 },
                new Country { Id =116,Name = "Singapore",Population = 5312400 ,WorldPercentage = 0.075 },
                new Country { Id =117,Name = "Turkmenistan",Population = 5240000 ,WorldPercentage = 0.074 },
                new Country { Id =118,Name = "Norway",Population = 5063709 ,WorldPercentage = 0.071 },
                new Country { Id =119,Name = "Lebanon",Population = 4822000 ,WorldPercentage = 0.068 },
                new Country { Id =120,Name = "Costa Rica",Population = 4667096 ,WorldPercentage = 0.066 },
                new Country { Id =121,Name = "Central African Republic",Population = 4616000 ,WorldPercentage = 0.065 },
                new Country { Id =122,Name = "Ireland",Population = 4585400 ,WorldPercentage = 0.065 },
                new Country { Id =123,Name = "Georgia[13]",Population = 4483800 ,WorldPercentage = 0.063 },
                new Country { Id =124,Name = "New Zealand",Population = 4471380 ,WorldPercentage = 0.063 },
                new Country { Id =125,Name = "Republic of the Congo",Population = 4448000 ,WorldPercentage = 0.063 },
                new Country { Id =126,Name = "Palestine[14]",Population = 4420549 ,WorldPercentage = 0.062 },
                new Country { Id =127,Name = "Liberia",Population = 4294000 ,WorldPercentage = 0.06 },
                new Country { Id =128,Name = "Croatia",Population = 4290612 ,WorldPercentage = 0.06 },
                new Country { Id =129,Name = "Bosnia and Herzegovina",Population = 3839737 ,WorldPercentage = 0.054 },
                new Country { Id =130,Name = "Oman",Population = 3831553 ,WorldPercentage = 0.054 },
                new Country { Id =131,Name = "Puerto Rico (USA)",Population = 3667084 ,WorldPercentage = 0.052 },
                new Country { Id =132,Name = "Kuwait",Population = 3582054 ,WorldPercentage = 0.05 },
                new Country { Id =133,Name = "Moldova[15]",Population = 3559500 ,WorldPercentage = 0.05 },
                new Country { Id =134,Name = "Mauritania",Population = 3461041 ,WorldPercentage = 0.049 },
                new Country { Id =135,Name = "Panama",Population = 3405813 ,WorldPercentage = 0.048 },
                new Country { Id =136,Name = "Uruguay",Population = 3286314 ,WorldPercentage = 0.046 },
                new Country { Id =137,Name = "Armenia",Population = 3031200 ,WorldPercentage = 0.043 },
                new Country { Id =138,Name = "Lithuania",Population = 2960733 ,WorldPercentage = 0.042 },
                new Country { Id =139,Name = "Albania",Population = 2821977 ,WorldPercentage = 0.04 },
                new Country { Id =140,Name = "Mongolia",Population = 2754685 ,WorldPercentage = 0.039 },
                new Country { Id =141,Name = "Jamaica",Population = 2711476 ,WorldPercentage = 0.038 },
                new Country { Id =142,Name = "Namibia",Population = 2113077 ,WorldPercentage = 0.03 },
                new Country { Id =143,Name = "Lesotho",Population = 2074000 ,WorldPercentage = 0.029 },
                new Country { Id =144,Name = "Slovenia",Population = 2060461 ,WorldPercentage = 0.029 },
                new Country { Id =145,Name = "Macedonia",Population = 2059794 ,WorldPercentage = 0.029 },
                new Country { Id =146,Name = "Botswana",Population = 2024904 ,WorldPercentage = 0.029 },
                new Country { Id =147,Name = "Latvia",Population = 2013400 ,WorldPercentage = 0.028 },
                new Country { Id =148,Name = "Qatar",Population = 1963124 ,WorldPercentage = 0.028 },
                new Country { Id =149,Name = "Gambia",Population = 1849000 ,WorldPercentage = 0.026 },
                new Country { Id =150,Name = "Guinea-Bissau",Population = 1704000 ,WorldPercentage = 0.024 },
                new Country { Id =151,Name = "Gabon",Population = 1672000 ,WorldPercentage = 0.024 },
                new Country { Id =152,Name = "Equatorial Guinea",Population = 1622000 ,WorldPercentage = 0.023 },
                new Country { Id =153,Name = "Trinidad and Tobago",Population = 1328019 ,WorldPercentage = 0.019 },
                new Country { Id =154,Name = "Estonia",Population = 1286540 ,WorldPercentage = 0.018 },
                new Country { Id =155,Name = "Mauritius",Population = 1257900 ,WorldPercentage = 0.018 },
                new Country { Id =156,Name = "Swaziland",Population = 1250000 ,WorldPercentage = 0.018 },
                new Country { Id =157,Name = "Bahrain",Population = 1234571 ,WorldPercentage = 0.017 },
                new Country { Id =158,Name = "Timor-Leste",Population = 1066409 ,WorldPercentage = 0.015 },
                new Country { Id =159,Name = "Djibouti",Population = 864618 ,WorldPercentage = 0.012 },
                new Country { Id =160,Name = "Cyprus[16]",Population = 862 ,WorldPercentage = 0.012 },
                new Country { Id =161,Name = "Fiji",Population = 858038 ,WorldPercentage = 0.012 },
                new Country { Id =162,Name = "Réunion (France)",Population = 821136 ,WorldPercentage = 0.012 },
                new Country { Id =163,Name = "Guyana",Population = 784894 ,WorldPercentage = 0.011 },
                new Country { Id =164,Name = "Bhutan",Population = 73674 ,WorldPercentage = 0.01 },
                new Country { Id =165,Name = "Comoros",Population = 7243 ,WorldPercentage = 0.01 },
                new Country { Id =166,Name = "Montenegro",Population = 620029 ,WorldPercentage = 0.0087 },
                new Country { Id =167,Name = "Macau (China)",Population = 582 ,WorldPercentage = 0.0082 },
                new Country { Id =168,Name = "Western Sahara[17]",Population = 567 ,WorldPercentage = 0.008 },
                new Country { Id =169,Name = "Solomon Islands",Population = 561 ,WorldPercentage = 0.0079 },
                new Country { Id =170,Name = "Luxembourg",Population = 537 ,WorldPercentage = 0.0076 },
                new Country { Id =171,Name = "Suri,Name",Population = 534189 ,WorldPercentage = 0.0075 },
                new Country { Id =172,Name = "Cape Verde",Population = 491875 ,WorldPercentage = 0.0069 },
                new Country { Id =173,Name = "Malta",Population = 416055 ,WorldPercentage = 0.0059 },
                new Country { Id =174,Name = "Guadeloupe (France)",Population = 403355 ,WorldPercentage = 0.0057 },
                new Country { Id =175,Name = "Martinique (France)",Population = 394173 ,WorldPercentage = 0.0056 },
                new Country { Id =176,Name = "Brunei",Population = 393162 ,WorldPercentage = 0.0055 },
                new Country { Id =177,Name = "Bahamas",Population = 351461 ,WorldPercentage = 0.0049 },
                new Country { Id =178,Name = "Iceland",Population = 32381 ,WorldPercentage = 0.0045 },
                new Country { Id =179,Name = "Maldives",Population = 31728 ,WorldPercentage = 0.0045 },
                new Country { Id =180,Name = "Belize",Population = 312971 ,WorldPercentage = 0.0044 },
                new Country { Id =181,Name = "Barbados",Population = 2742 ,WorldPercentage = 0.0039 },
                new Country { Id =182,Name = "French Polynesia (France)",Population = 26827 ,WorldPercentage = 0.0038 },
                new Country { Id =183,Name = "Vanuatu",Population = 258213 ,WorldPercentage = 0.0036 },
                new Country { Id =184,Name = "New Caledonia (France)",Population = 255651 ,WorldPercentage = 0.0036 },
                new Country { Id =185,Name = "French Guiana (France)",Population = 22904 ,WorldPercentage = 0.0032 },
                new Country { Id =186,Name = "Mayotte (France)",Population = 2126 ,WorldPercentage = 0.003 },
                new Country { Id =187,Name = "Samoa",Population = 18782 ,WorldPercentage = 0.0026 },
                new Country { Id =188,Name = "São Tomé and Príncipe",Population = 187356 ,WorldPercentage = 0.0026 },
                new Country { Id =189,Name = "Saint Lucia",Population = 166526 ,WorldPercentage = 0.0023 },
                new Country { Id =190,Name = "Guam (USA)",Population = 159358 ,WorldPercentage = 0.0022 },
                new Country { Id =191,Name = "Curaçao (Netherlands)",Population = 150563 ,WorldPercentage = 0.0021 },
                new Country { Id =192,Name = "Saint Vincent and the Grenadines",Population = 109 ,WorldPercentage = 0.0015 },
                new Country { Id =193,Name = "United States Virgin Islands (USA)",Population = 106405 ,WorldPercentage = 0.0015 },
                new Country { Id =194,Name = "Kiribati",Population = 104573 ,WorldPercentage = 0.0015 },
                new Country { Id =195,Name = "Grenada",Population = 103328 ,WorldPercentage = 0.0015 },
                new Country { Id =196,Name = "Tonga",Population = 103036 ,WorldPercentage = 0.0015 },
                new Country { Id =197,Name = "Federated States of Micronesia",Population = 101823 ,WorldPercentage = 0.0014 },
                new Country { Id =198,Name = "Aruba (Netherlands)",Population = 101484 ,WorldPercentage = 0.0014 },
                new Country { Id =199,Name = "Jersey (UK)",Population = 97857 ,WorldPercentage = 0.0014 },
                new Country { Id =200,Name = "Seychelles",Population = 90945 ,WorldPercentage = 0.0013 },
                new Country { Id =201,Name = "Antigua and Barbuda",Population = 86295 ,WorldPercentage = 0.0012 },
                new Country { Id =202,Name = "Isle of Man (UK)",Population = 84497 ,WorldPercentage = 0.0012 },
                new Country { Id =203,Name = "Andorra",Population = 76246 ,WorldPercentage = 0.0011 },
                new Country { Id =204,Name = "Dominica",Population = 71293 ,WorldPercentage = 0.001 },
                new Country { Id =205,Name = "Bermuda (UK)",Population = 64237 ,WorldPercentage = 0.0009 },
                new Country { Id =206,Name = "Guernsey (UK)",Population = 62431 ,WorldPercentage = 0.00088 },
                new Country { Id =207,Name = "Greenland (Denmark)",Population = 5637 ,WorldPercentage = 0.00079 },
                new Country { Id =208,Name = "Marshall Islands",Population = 55548 ,WorldPercentage = 0.00078 },
                new Country { Id =209,Name = "American Samoa (USA)",Population = 55519 ,WorldPercentage = 0.00078 },
                new Country { Id =210,Name = "Cayman Islands (UK)",Population = 55456 ,WorldPercentage = 0.00078 },
                new Country { Id =211,Name = "Saint Kitts and Nevis",Population = 54 ,WorldPercentage = 0.00076 },
                new Country { Id =212,Name = "Northern Mariana Islands (USA)",Population = 53883 ,WorldPercentage = 0.00076 },
                new Country { Id =213,Name = "Faroe Islands (Denmark)",Population = 48244 ,WorldPercentage = 0.00068 },
                new Country { Id =214,Name = "Sint Maarten (Netherlands)",Population = 37429 ,WorldPercentage = 0.00053 },
                new Country { Id =215,Name = "Saint Martin (France)",Population = 36979 ,WorldPercentage = 0.00052 },
                new Country { Id =216,Name = "Liechtenstein",Population = 36842 ,WorldPercentage = 0.00052 },
                new Country { Id =217,Name = "Monaco",Population = 36136 ,WorldPercentage = 0.00051 },
                new Country { Id =218,Name = "San Marino",Population = 32382 ,WorldPercentage = 0.00046 },
                new Country { Id =219,Name = "Turks and Caicos Islands (UK)",Population = 31458 ,WorldPercentage = 0.00044 },
                new Country { Id =220,Name = "Gibraltar (UK)",Population = 29752 ,WorldPercentage = 0.00042 },
                new Country { Id =221,Name = "British Virgin Islands (UK)",Population = 29537 ,WorldPercentage = 0.00042 },
                new Country { Id =222,Name = "Åland Islands (Finland)",Population = 28502 ,WorldPercentage = 0.0004 },
                new Country { Id =223,Name = "Caribbean Netherlands (Netherlands)",Population = 21133 ,WorldPercentage = 0.0003 },
                new Country { Id =224,Name = "Palau",Population = 2077 ,WorldPercentage = 0.00029 },
                new Country { Id =225,Name = "Cook Islands (NZ)",Population = 14974 ,WorldPercentage = 0.00021 },
                new Country { Id =226,Name = "Anguilla (UK)",Population = 13452 ,WorldPercentage = 0.00019 },
                new Country { Id =227,Name = "Wallis and Futuna (France)",Population = 13152 ,WorldPercentage = 0.00019 },
                new Country { Id =228,Name = "Tuvalu",Population = 11264 ,WorldPercentage = 0.00016 },
                new Country { Id =229,Name = "Nauru",Population = 9945 ,WorldPercentage = 0.00014 },
                new Country { Id =230,Name = "Saint Barthélemy (France)",Population = 8938 ,WorldPercentage = 0.00013 },
                new Country { Id =231,Name = "Saint Pierre and Miquelon (France)",Population = 6081 ,WorldPercentage = 0.00006 },
                new Country { Id =232,Name = "Montserrat (UK)",Population = 4922 ,WorldPercentage = 0.00005 },
                new Country { Id =233,Name = "Saint Helena Ascension and Tristan da Cunha (UK)",Population = 4 ,WorldPercentage = 0.00004 },
                new Country { Id =234,Name = "Svalbard and Jan Mayen (Norway)",Population = 2655 ,WorldPercentage = 0.00003 },
                new Country { Id =235,Name = "Falkland Islands (UK)",Population = 2563 ,WorldPercentage = 0.00003 },
                new Country { Id =236,Name = "Norfolk Island (Australia)",Population = 2302 ,WorldPercentage = 0.00002 },
                new Country { Id =237,Name = "Christmas Island (Australia)",Population = 2072 ,WorldPercentage = 0.00002 },
                new Country { Id =238,Name = "Niue (NZ)",Population = 1613 ,WorldPercentage = 0.00002 },
                new Country { Id =239,Name = "Tokelau (NZ)",Population = 1411 ,WorldPercentage = 0.00001 },
                new Country { Id =240,Name = " Vatican City",Population = 800 ,WorldPercentage = 0.00001 },
                new Country { Id =241,Name = "Cocos (Keeling) Islands (Australia)",Population = 550 ,WorldPercentage = 0.000001 },
                new Country { Id =242,Name = "Pitcairn Islands (UK)",Population = 66 ,WorldPercentage = 0.0000000 }
            };

        }

    }

}

As you can see, we must tag the service with the ScriptService and tag the WebMethod with the ScriptMethod attribute, specifying the JSON responseformat. We also need to add some to our web.config:

<?xml version="1.0"?>

<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <webServices>
      <protocols>
        <add name="HttpGet" />
        <add name="HttpPost"/>
      </protocols>
    </webServices>

  </system.web>

</configuration>


We also need some GUI here to test out the TypeAhead control:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head<
    <title></title>
    <link href="Content/bootstrap.css" rel="stylesheet" />
    <link href="Content/bootstrap-responsive.css" rel="stylesheet" />
</head>
<body>

    <div class="row">

    <div class="span12">
    <input type="text" id="tbCountries" /> 
   

    </div class="row">
   
    <script src="Scripts/jquery-2.0.3.js"></script>
    <script src="Scripts/bootstrap.js"></script>
    <script src="Scripts/underscore.js"></script>

    <script type="text/javascript">

        $(function () {
         

            var countries;

            $("#tbCountries").typeahead({
                source: function (query, process) {
                    return $.ajax({
                        type: "POST",
                        url: 'http://localhost:52523/CountryService.asmx/GetCountries',
                        data: JSON.stringify({query: query }),
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                        success:
                        function (data) {
                            countries = data.d; 
                            var countryIds = _.map(countries, function(c){
                                return c.Id; 
                            }); 
                            return process(countryIds);
                        }
                    });
                },
                matcher: function (item) {
                    return true;
                },
                sorter: function (items) {
                    return items;
                },
                highlighter: function (id) {
                    var country = _.find(countries, function (c) {
                        return c.Id == id;
                    });
                    return country.Name + " Population: " + country.Population; 
                },
                updater: function (id) {
                    var country = _.find(countries, function (c) {
                        return c.Id == id;
                    });
                    return country.Name;
                }
            });

        });

    </script>
</body>
</html>


To sum up, to make the TypeAhead control work in my example, I had to implement stub implementations of matcher, sorter, highlighter (must be implemented such that the custom Country object instances return in JSON object is visible, this is a display template in other words) and updater (will update the text field with the autocomplete / TypeAhead feature). Source also sets a global variable countries here for simplicity, and continues processing the ids, you can see that we use Underscore.Js here for the array processing. The highlighter and updater method uses the find method of Underscore.js to find the relevant country. The end result is a functioning auto complete example for the Bootstrap TypeAhead control that uses a remote JSON service. I am not sure why the data.d variable was returned from the service. I did not specify "data.d" anywhere in my code, but this is where I could find the returned JSON data. It is not very elegant to set the countries to a global variable, we could of course encapsulate this better using a "provider" to encapsulate the data for encapsulation and consistency protection. But the key point of this article was to help others getting started with the TypeAhead control in Bootstrap with remote JSON calls returning objects with properties and not just simple string arrays. I find the Bootstrap documentation from Twitter as good, but not exemplary. It is sometimes hard to find good programming examples on the different controls. The end result is an autocomplete control that looks nice and can display compound data:

Wednesday, 24 July 2013

Structuring your Javascript code - Revealing prototype pattern and namespaces

Creating Spaghetti-code in Javascript is not difficult. There are no clear pattern in Javascript for encapsulation for novice developers of Javascript, unless you really are familiar with what is possible with Javascript. Most developers learn Javascript in an ad-hoc manner, just adding functions to a Javascript file and keep on adding code to their monolithic design until they realize that a pattern must be used to structure the Javascript code. Of course, today, with the huge focus on Javascript, there are multiple patterns to follow and coding Javascript is a more mature topic that it used to be. There are four designs which we can choose when we structure our code (possible more):
  • Module pattern
  • Prototype pattern
  • Revealing module pattern
  • Revealing prototype pattern
We will in this article focus on the last, the revealing prototype pattern. This pattern allows refactoring the Javascript code, i.e. extensibility, and it also offers encapsulation. It is the most flexible and still rigid solution. It is not difficult to understand either, once you see an example which I will present next. In our example, we use LocalStorage, which is allows saving data on the client side through the browser. It is quicker and safer than ordinary cookies. We will encapsulate the logic of saving to the LocalStorage with a simple class-like structure in Javascript. Of course, I could have used TypeScript here and just create a class, but this article is more focused about explaining the concepts so you can recognize this pattern when you read Javascript code later on that uses this pattern and understand what is going on. Let's look at the Javascript class following the revealing prototype pattern next:

var AppUtils = AppUtils || {}; 

AppUtils.LocalStorageUtility = function(storageKeys, sourceElements, feedbackElement) {
    this.storageKeys = storageKeys;
    this.sourceElements = sourceElements; 
    this.feedbackElement = feedbackElement;
};

AppUtils.LocalStorageUtility.prototype = (function () {

        var storeSettings = function (thisObj) {
            for (var i = 0; i < thisObj.storageKeys.length; i++) {
                var storageKey = thisObj.storageKeys[i]; 
                var elementName = thisObj.sourceElements[i];
                localStorage.setItem(storageKey, $("#" + elementName).val());  
            }
            $("#" + thisObj.feedbackElement).text("Local setting saved!");
        },
        loadSettings = function (thisObj) {

            for (var i = 0; i < thisObj.storageKeys.length; i++) {
                var storageKey = thisObj.storageKeys[i]; 
                var elementName = thisObj.sourceElements[i];
                $("#" + elementName).val(localStorage.getItem(storageKey)); 
            }

            $("#" + thisObj.feedbackElement).text("Local setting loaded!");
        },
        clearSettings = function () {
            localStorage.clear(); 
        },
         hasLocalStorage = function () {
            return typeof (Storage) !== "undefined"; 
        }

        return {
            StoreSettings: storeSettings,
            LoadSettings: loadSettings,
            ClearSettings: clearSettings,
            HasLocalStorage: hasLocalStorage
        };

})(); 

The consumer of this class-like structure in Javascript will provide two string arrays which is the local storage key names and the elements to read and store local storage values from. I do not do any checking here that the two arrays are the same length or that they are of the correct type (arrays preferably with string of course). This is what TypeScript version of this code would specify. Remember, TypeScript is much easier to use than manually creating class like structs like we do here, but the concepts are anyways important to understand. In the revealing prototype pattern we return an object literal and the public part is exposed here, i.e. the revealing prototype. In addition, we call it revealing because the prototype is self invoking. The private parts are what is outside of the return statement above. We point to the private methods, and this is fine, and we alias them to a capitalized version to let the user call into the private methods. If we want public fields We also need a GUI for the Javascript code here:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Localstorage demo</title>
</head>

<script src="Scripts/jquery-2.0.3.min.js"></script>
    <script src="Scripts/LocalStorageUtility.js"></script>
    
    <script type="text/javascript">

        $(document).ready(function () {
            var ls = new AppUtils.LocalStorageUtility(["Name", "City"], ["tbName", "tbCity"], "lblFeedback"); 

            if (ls.HasLocalStorage) {
                $("#lblFeedback").text("Local storage is enabled!"); 
            }
            else {
                $("#lblFeedback").text("Local storage is disabled!"); 
            }

            $("#btnLoadSettings").click(function () { ls.LoadSettings(ls); }); 
            $("#btnSaveSettings").click(function () { ls.StoreSettings(ls); }); 
            $("#btnClearSettings").click(ls.ClearSettings); 
        }); 

    </script>

<body>

    <table>
        <tr>
            <td>Name</td><td><input id="tbName" type="text" /></td>
            <td>City</td><td><input id="tbCity" type="text" /></td>
        </tr>
    </table>
  
    <button id="btnLoadSettings" type="button">Load settings</button>

    <button id="btnSaveSettings" type="button">Save settings</button>

    <button id="btnClearSettings" type="button">Clear settings</button>    

    <p id="lblFeedback" style="color: darkgreen">ready</p>

</body>
</html>


As you can see, with this pattern we must keep track of the this pointer in the prototype definition. There are alternatives, such as bind, and call, but I wanted to keep the example clear. In the jQuery load method above we define click handlers that pass in the instance of the LocalStorageUtility, which we have instantiated, such that the prototype gets the correct instance. As you perhaps know, the prototype must bind to the correct this pointer, and here we explicitly pass it in (i.e. the instance of LocalStorageUtility). Finally, note that we define a namespace here with the "or empty object literal" technique. This allows us to hide the entire class from the global namespace and improve or encapsulation even more. If you have comments to the code above, please let me know. I have worked some with Javascript of course, but I am still learning a lot about it.

Saturday, 20 July 2013

Presentation of Underscore.Js

Underscore.Js library presentation

I am working with a presentation of Underscore.Js Javascript library. The powerpoint file (.pptx) is available for download here:

Underscore.Js presentation [PPTX]



Underscore.Js presentation [PDF]

Created with Powerpoint 2013.