Tuesday 7 October 2014

The certificate for the signer of the message is invalid or not found

A Colleuge of Mine was running the new Microsoft CRM SDK however when he tried to execute the Application it kept failing in:
Microsoft.IdentityModel accompanied with this message in Visual Studio: 'Could not load file or assembly ‘Microsoft.IdentityModel Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencie. The system cannot fine the find specified.'

When I downloaded the WIF from Microsoft and Installed Its Application then I seen this:

SOLUTION : After doing a little research, I discovered that Windows Identity Foundation is built into Windows 8.1 that you can add via Add Programs and Features

After selecting Windows Identity Foundation 3.5 from the Add Roles and Features Wizard, I clicked Next and then Install. Once the installation wizard completed I run my application and it worked without any Issue. Well I did need to restart Visual Studio.

Friday 12 September 2014

Updating Images on the Fly

Streaming RAW Images to a Page. If you wish to stream an image to a page the easiest method is to convert it to a Binary 64 data type. Red dot This will enable IE to render the image as if it was stored on the server. Intrestingly this concept could work on the premise of playing a silent video clip at 1 frame per second in that if we store the Binary in a database we could in theory poll AJAX to and stream the image every second to the browsers image control updating it on the fly. In a company where I previously worked we used this approach to enable the user to scroll through footage as we took Keyframes every so many seconds that they could in essence watch the feed.

Monday 1 September 2014

Force File Download

Sometimes instead of letting a user view an Image or PDF I would rather them download it, This method below Forces the File (Doc / MP3 / PDF / Images) etc.. to be downloaded rather than rendered. This can save time and bandwidth on a website rather than the user continaully streaming the data on a frequent basis.
namespace FieldOfSheep
{
public class FileDownloadExtensions
{
 public static void ForceFileDownload(MemoryStream s, string fileName)
        {
            if (HttpContext.Current != null)
            {
                var responseObject = HttpContext.Current.Response;

                if (responseObject.IsClientConnected && s != null)
                {
                    responseObject.Clear();
                    responseObject.ContentType = "application/octet-stream";
                    responseObject.AddHeader("Content-Disposition",
                        "attachment; filename=" + fileName);

                    responseObject.BinaryWrite(s.ToArray());

                    responseObject.Flush();

                    responseObject.Close();
                }
            }
        }
 }
}       

Saturday 16 August 2014

ServiceStack Object Dump

There are times when you may need to dump an entire object to JSON for storing or for viewing, One example is to run an Object Dump on an Object or class at each step of a registraion page to see what the user is entering rather than getting final data at the end. This would help some people to see why users are dropping off the site for example. This is where 'ServiceStack.NET' comes into play - It has methods that support this functionality and one method is the 'Dump' method. Its rather simple and easy to use here is a working example.
  
  using ServiceStack.Text;
namespace FieldOfSheep
{  
  public static void Main(String[] args)
  {
     object myClass;
     var str = myClass.Dump();
    
     //Str now contains the JSON Values inside 'Object'
     
  }
}

Friday 25 July 2014

Integer Extension

When using Linq & Lambda expressions I find it easier to write a word based approach than writing long hand. Take for example this query
var something = (from myObject in myTable where myObject.Number > 1 && myObject.Number < 10 select myObject);
We could simply make this code cleaner and easier to read by writing
var something = (from myObject in myTable where myObject.Number.IsWithin(1,10) select myObject);
And the brains behind this method is this little extension method.
namespace FieldOfSheep
{
public static class IntegerExtensions
    {
        public static bool IsWithin(this int value, int minimum, int maximum)
        {
            return value >= minimum && value <= maximum;
        }
    }
}

Thursday 24 July 2014

Sanity Checker

Some times I need to run RegEx Scripts on text boxes. Here is a simple RegEx Sanity Checker for ASP.NET - You can download this from my SourceForge Page
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace FieldOfSheep
{
    [ToolboxData("<{0}:SanityChecker runat=server>")]
    public class SanityChecker : TextBox
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Page.ClientScript.RegisterClientScriptBlock(typeof(string), "SanityChecker.js", JScript.SanityChecker, true);

            this.Attributes.Add("onkeyup", string.Format("return SanityChecker(event,'{0}');", this.ClientID));

       }
    }
}
And the JavaScript code for this is
function SanityChecker(evt, element)
{
    var charCode = (evt.which) ? evt.which : event.keyCode;
    if(charCode > 93 && charCode < 112 || charCode > 46 && charCode < 91 || charCode > 185 && charCode < 223)
    {
        var rex = /^[^<>&\"\';]*$/;
        var value = document.getElementById(element).value;
        if(rex.test(str))
        {
            return true;
        }
        else
        {
            
            value = str.substring(0,value.length -1);
            document.getElementById(element).value = value;
        }
    }
}

Thursday 12 June 2014

Printing a Remote Document Using Aspose.Words to a Network Printer.

Sometimes clients need to print documents from Internal non public facing websites. At times there are also user access considerations in that we do not want to give them direct access to the file. For this we allow them the option to print the document to a designated printer on their network. We can do this by creating a simple printing method that takes a URL / Downloads It on the Server / Renders It Through Aspose and Prints it to a Network printer. Step 1. Identify the Network Printer we can display printers running this command
public static void Main(string[] args)
{
     DropDownList list = new DropDownList();
     
     System.Drawing.Printing.PrinterSettings.InstalledPrinters.Cast().ForEach
     (
         y => this.ddlPrinters.Items.Add(y)            
     );
}
Step 2. Run this method
var couldPrint = PrintDocument("http://www.somesite.com/somedocument.doc", this.ddlPrinters.SelectedValue);
Which in turn runs this block of code. Step 3.
public static bool PrintDocument(string uriToDocument, string printerName)
        {
            try
            {
                HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uriToDocument);
                myReq.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]);
                WebResponse myResp = myReq.GetResponse();

                StreamReader reader = new StreamReader(myResp.GetResponseStream());

                MemoryStream ms = new MemoryStream();

                reader.BaseStream.CopyTo(ms);

                if (Path.GetExtension(uriToDocument) == ".doc" || Path.GetExtension(uriToDocument) == ".docx")
                {
 
                    Aspose.Words.Document document = new Aspose.Words.Document(ms);

                    document.Print(printerName);

                }
                return true;
            }
            catch (Exception ex)
            {
                //Log to your database here.
            }

            return false;
        }

Friday 23 May 2014

Insert Email Into Exchange Public Folder - Adding (2 of 2)

In one of our products we are required to insert an email item into exchange, After much nail biting after realising that Microsoft Exchange WebService Documentation is extremely poor. I have come up with a solution that accepts a FileInfo Object and a FileStream and puts the file into a 'Public Folder' into exchange. Heres the code

public static void InsertIntoExchange(FileInfo file, FileStream stream)
        {
           
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    if (stream.Length == 0)
                        throw new Exception(string.Format("File Error: {0} Contains Zero Bytes",file.FullName));

                    Folder selectedPublicFolder = null;

                    //Set your Aspose Licence Here

                    MapiMessage mapiMessage = MapiMessage.FromStream(stream);
                    mapiMessage.Save(ms);

                    var properties = mapiMessage.NamedProperties.Values.Cast().ToList();

                    var propProjectId = properties.Where(y => y.NameId == "ProjectID").FirstOrDefault();
                    var propFileStatus = properties.Where(y => y.NameId == "FileStatus").FirstOrDefault();

                    if (propProjectId != null && propFileStatus != null)
                    {
                        string projectId = propProjectId.GetString();
                        Enumerators.FileStatus fileStatus = (Enumerators.FileStatus)Enum.Parse(typeof(Enumerators.FileStatus), propFileStatus.GetString());

                        if (fileStatus == Enumerators.FileStatus.Uploaded)
                        {
                              throw new Exception("File Already Uploaded");
                        }
                        else if (fileStatus == Enumerators.FileStatus.Failed)
                        {
                            throw new Exception("File Failed");
                        }
                        else
                        {
                            selectedPublicFolder = //Find Exchange Public Folder

                            if (selectedPublicFolder == null)
                            {
    throw new Exception("Public Folder Was Not Found");                                
                            }

                            FolderIdType f = new FolderIdType();
                            f.Id = selectedPublicFolder.Id.UniqueId;

                            try
                            {
                                CreateItemType ciType = new CreateItemType()
                                {
                                    MessageDisposition = MessageDispositionType.SaveOnly,
                                    MessageDispositionSpecified = true,
                                    SavedItemFolderId = new TargetFolderIdType()
                                    {
                                        Item = f
                                    },
                                    Items = new NonEmptyArrayOfAllItemsType()
                                };


                                using (MemoryStream tms = new MemoryStream())
                                {
                                    //Load AsposeLicence Again

                                    MailMessage m = MailMessage.Load(stream);
                                    m.Save(tms);

                                    MessageType msg = new MessageType()
                                    {

                                        MimeContent = new MimeContentType()
                                        {
                                            Value = Convert.ToBase64String(tms.ToArray())
                                        },

                                        IsRead = true
                                    };

                                    ExtendedPropertyType type = new ExtendedPropertyType();

                                    PathToExtendedFieldType epExPath = new PathToExtendedFieldType();
                                    epExPath.PropertyTag = "0x0E07";
                                    epExPath.PropertyType = MapiPropertyTypeType.Integer;

                                    type.ExtendedFieldURI = epExPath;
                                    type.Item = "1";

                                    msg.DateTimeSent = m.Date;
                                    
                                    msg.ExtendedProperty = new ExtendedPropertyType[1];
                                    msg.ExtendedProperty[0] = type;

                                    ciType.Items.Items = new ItemType[1];
                                    ciType.Items.Items[0] = msg;

                                    CreateItemResponseType response = Global.ExchangeServiceBinding.CreateItem(ciType);


                                    if (response.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                                    {
                                        throw new Exception(response.ResponseMessages.Items[0].MessageText);
                                    }

                                }

                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                            finally
                            {
                                mapiMessage.NamedProperties.Remove(propFileStatus.Tag);

                                MapiNamedPropertyMappingStorage mappingStorage = mapiMessage.NamedPropertyMapping;
                                Guid PS_PUBLIC_STRINGS = new Guid("00020329-0000-0000-C000-000000000046");

                                // Create a named property
                                MapiProperty stringProperty = new MapiProperty(mappingStorage.GetNextAvailablePropertyId(Aspose.Email.Outlook.MapiPropertyType.PT_UNICODE),
                                                        Encoding.Unicode.GetBytes(((int)fileStatus).ToString()));

                                // Set message property
                                mapiMessage.SetProperty(stringProperty);
                                string stringNameId = "FileStatus";
                                mappingStorage.AddNamedPropertyMapping(stringProperty, stringNameId, PS_PUBLIC_STRINGS);

                                stream.Close();

                                mapiMessage.Save(file.FullName);
                            }
                        }


                    }


                    else if (propProjectId == null)
                    {
                        throw new Exception("File Failure: Project ID was not found in file: " + file.Name);

                    }
                    else if (propFileStatus == null)
                    {
                        throw new Exception("File Failure: FileStatus was not found in file: " + file.Name);
                    }
                    else
                    {
                        throw new Exception("File Failure: The File May Not Be a valid file: " + file.Name);                        
                    }
                }

            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

If however you are using Exchange 2010 the best way is to insert the object into the 'Inbox' First then perform a 'Move' operation as Exchange Mangles the Header and Mime object if a direct insert occurs. Add this at the end of the Insertion Method Above
//*Attempt to Move Item *//
                                            var newId = (((ExchangeWebServices.ItemInfoResponseMessageType)
                                                (((ExchangeWebServices.BaseResponseMessageType) (response))
                                                    .ResponseMessages.Items[0]))
                                                .Items.Items[0]).ItemId;

                                            if (newId != null)
                                            {
                                                MoveItemType t = new MoveItemType()
                                                {
                                                    ItemIds = new BaseItemIdType[]
                                                    {
                                                        newId
                                                    },

                                                };
                                                t.ToFolderId = new TargetFolderIdType();
                                                t.ToFolderId.Item = f;

                                                var moveItemResponse = Global.ExchangeServiceBinding.MoveItem(t);

                                                if (response.ResponseMessages.Items[0].ResponseClass ==
                                                    ResponseClassType.Error)
                                                {
                                                    throw new Exception("File Uploaded but it failed to move from Inbox");
                                                }

                                            }

Monday 21 April 2014

Insert Email into Exchange Public Folder - Searching (1 of 2)

Here is a method that will enable you to search for a Public Folder In Exchange. It returns a 'Folder' object which we can use to insert objects to. We Need however to specify a 'Root' Folder as well as the 'ExchangeServiceBinding' object.
public static Folder FindPublicFolderByName(ExchangeService svc, string folderName)
        {
            FolderView folderView = new FolderView(int.MaxValue);
            FindFoldersResults findFoldersResults = svc.FindFolders(WellKnownFolderName.PublicFoldersRoot, folderView);

            foreach (var folder in findFoldersResults)
            {
                if (folderName.Equals(folder.DisplayName, StringComparison.InvariantCultureIgnoreCase))
                {
                    return folder;
                }
                else if (folder.ChildFolderCount > 0)
                {
                    Folder f =  FindFolderByNameRecursive(svc, folder, folderName);

                    if (f != null)
                        return f;
                }
            }

            throw new Exception("Folder Not Found: " + folderName);
        }

        private static Folder FindFolderByNameRecursive(ExchangeService s, Folder f, string folderName)
        {
            FolderView folderView = new FolderView(int.MaxValue);

            FindFoldersResults findFoldersResults = s.FindFolders(f.Id, folderView);

            foreach (Folder folder in findFoldersResults)
            {
                if (folderName.Equals(folder.DisplayName, StringComparison.InvariantCultureIgnoreCase))
                {
                    return folder;
                }
                else if (folder.ChildFolderCount > 0)
                {
                    Folder f2 = FindFolderByNameRecursive(s, folder, folderName);

                    if (f2 != null)
                        return f2;
                }
            }
            return null;
        }

Wednesday 19 February 2014

Convert XmlNode to DataSet

Here is a function that will enable you to pass a valid XML Node and have the system return you a DataSet object that you can use to manipulate further. Good bye nasty XML!

namespace FieldOfSheep
{
public static class NodeXmlExtension
    {
        public static DataSet ConvertToDataSet(this XmlNode node)
        {
            //declaring data set object
            DataSet dataset = null;
            if (node != null)
            {
                XmlTextReader xtr = new XmlTextReader(node.OuterXml, XmlNodeType.Element, null);
                dataset = new DataSet();
                dataset.ReadXml(xtr);
            }

            return dataset;
        }
    }
}
This class above is intended for use as an extension method to be used like so.

using FieldOfSheep;

public static void Main(String[] args)
{
   XmlNode node;

   DataSet ds = node.ConvertToDataSet();

}


Sunday 16 February 2014

There are times when building software that our customer asks us to create items that are out of the box. One such request was to integrate SagePay Tokenization to Nop Commerce 1.80. Having had experience on implementing SagePay for simple websites as well as development for NopCommerce I realised it should not be too difficult to marry the systems. Generally there are 3 components to the system 1) The Payment Class 2) The Notification Class 3) The Database What the system does is that it creates a payment Item that then spins out to SagePay directly, The Notification class is an intermediate website that communicates back and forward to enable SagePay to give us its transaciton information and weather or not a payment passed for failed. After this it then redirects to the appropriate page. It is a really complicated project and I will hopefully write about it later and explain more, However for now feel free to browse my source code directly on SourceForge to gain an overview of what it does.

Monday 3 February 2014

Remove ASP.NET Membership Database

Have you ever tried to remove the base aspnet_[table] and its associated views and stored procs if you have you probably know that its like a mine field to to remove each file in the correct order of its insertion.
I have realized that after some trial and error that there is a pattern to the table creation so we simply reverse this. To run the drop statements.
*WARNING* - Backup your database, I am in no way responsible for any idiots who incur data loss because of running this script
DROP VIEW vw_aspnet_Applications
DROP VIEW vw_aspnet_MembershipUsers
DROP VIEW vw_aspnet_Profiles
DROP VIEW vw_aspnet_Roles
DROP VIEW vw_aspnet_Users
DROP VIEW vw_aspnet_UsersInRoles
DROP VIEW vw_aspnet_WebPartState_Paths
DROP VIEW vw_aspnet_WebPartState_Shared
DROP VIEW vw_aspnet_WebPartState_User
 
DROP PROCEDURE aspnet_AnyDataInTables
DROP PROCEDURE aspnet_Applications_CreateApplication
DROP PROCEDURE aspnet_CheckSchemaVersion
DROP PROCEDURE aspnet_Membership_ChangePasswordQuestionAndAnswer
DROP PROCEDURE aspnet_Membership_CreateUser
DROP PROCEDURE aspnet_Membership_FindUsersByEmail
DROP PROCEDURE aspnet_Membership_FindUsersByName
DROP PROCEDURE aspnet_Membership_GetAllUsers
DROP PROCEDURE aspnet_Membership_GetNumberOfUsersOnline
DROP PROCEDURE aspnet_Membership_GetPassword
DROP PROCEDURE aspnet_Membership_GetPasswordWithFormat
DROP PROCEDURE aspnet_Membership_GetUserByEmail
DROP PROCEDURE aspnet_Membership_GetUserByName
DROP PROCEDURE aspnet_Membership_GetUserByUserId
DROP PROCEDURE aspnet_Membership_ResetPassword
DROP PROCEDURE aspnet_Membership_SetPassword
DROP PROCEDURE aspnet_Membership_UnlockUser
DROP PROCEDURE aspnet_Membership_UpdateUser
DROP PROCEDURE aspnet_Membership_UpdateUserInfo
DROP PROCEDURE aspnet_Paths_CreatePath
DROP PROCEDURE aspnet_Personalization_GetApplicationId
DROP PROCEDURE aspnet_PersonalizationAdministration_DeleteAllState
DROP PROCEDURE aspnet_PersonalizationAdministration_FindState
DROP PROCEDURE aspnet_PersonalizationAdministration_GetCountOfState
DROP PROCEDURE aspnet_PersonalizationAdministration_ResetSharedState
DROP PROCEDURE aspnet_PersonalizationAdministration_ResetUserState
DROP PROCEDURE aspnet_PersonalizationAllUsers_GetPageSettings
DROP PROCEDURE aspnet_PersonalizationAllUsers_ResetPageSettings
DROP PROCEDURE aspnet_PersonalizationAllUsers_SetPageSettings
DROP PROCEDURE aspnet_PersonalizationPerUser_GetPageSettings
DROP PROCEDURE aspnet_PersonalizationPerUser_ResetPageSettings
DROP PROCEDURE aspnet_PersonalizationPerUser_SetPageSettings
DROP PROCEDURE aspnet_Profile_DeleteInactiveProfiles
DROP PROCEDURE aspnet_Profile_DeleteProfiles
DROP PROCEDURE aspnet_Profile_GetNumberOfInactiveProfiles
DROP PROCEDURE aspnet_Profile_GetProfiles
DROP PROCEDURE aspnet_Profile_GetProperties
DROP PROCEDURE aspnet_Profile_SetProperties
DROP PROCEDURE aspnet_RegisterSchemaVersion
DROP PROCEDURE aspnet_Roles_CreateRole
DROP PROCEDURE aspnet_Roles_DeleteRole
DROP PROCEDURE aspnet_Roles_GetAllRoles
DROP PROCEDURE aspnet_Roles_RoleExists
DROP PROCEDURE aspnet_Setup_RemoveAllRoleMembers
DROP PROCEDURE aspnet_Setup_RestorePermissions
DROP PROCEDURE aspnet_UnRegisterSchemaVersion
DROP PROCEDURE aspnet_Users_CreateUser
DROP PROCEDURE aspnet_Users_DeleteUser
DROP PROCEDURE aspnet_UsersInRoles_AddUsersToRoles
DROP PROCEDURE aspnet_UsersInRoles_FindUsersInRole
DROP PROCEDURE aspnet_UsersInRoles_GetRolesForUser
DROP PROCEDURE aspnet_UsersInRoles_GetUsersInRoles
DROP PROCEDURE aspnet_UsersInRoles_IsUserInRole
DROP PROCEDURE aspnet_UsersInRoles_RemoveUsersFromRoles
DROP PROCEDURE aspnet_WebEvent_LogEvent
 
 
DROP TABLE aspnet_WebEvent_Events
DROP TABLE aspnet_SchemaVersions
DROP TABLE aspnet_Profile
DROP TABLE aspnet_UsersInRoles
DROP TABLE aspnet_Roles
DROP TABLE aspnet_PersonalizationPerUser
DROP TABLE aspnet_PersonalizationAllUsers
DROP TABLE aspnet_Paths
DROP TABLE aspnet_Membership
DROP TABLE aspnet_Users
DROP TABLE aspnet_Applications
 
DROP SCHEMA aspnet_Membership_FullAccess
DROP SCHEMA aspnet_Membership_ReportingAccess
DROP SCHEMA aspnet_Personalization_FullAccess
DROP SCHEMA aspnet_Membership_BasicAccess
DROP SCHEMA aspnet_Personalization_BasicAccess
DROP SCHEMA aspnet_Personalization_ReportingAccess
DROP SCHEMA aspnet_Profile_BasicAccess
DROP SCHEMA aspnet_Profile_FullAccess
DROP SCHEMA aspnet_Profile_ReportingAccess
DROP SCHEMA aspnet_Roles_BasicAccess
DROP SCHEMA aspnet_Roles_FullAccess
DROP SCHEMA aspnet_Roles_ReportingAccess
DROP SCHEMA aspnet_WebEvent_FullAccess
 
 
DROP ROLE aspnet_Membership_FullAccess
DROP ROLE aspnet_Membership_ReportingAccess
DROP ROLE aspnet_Personalization_FullAccess
DROP ROLE aspnet_Membership_BasicAccess
DROP ROLE aspnet_Personalization_BasicAccess
DROP ROLE aspnet_Personalization_ReportingAccess
DROP ROLE aspnet_Profile_FullAccess
DROP ROLE aspnet_Profile_ReportingAccess
DROP ROLE aspnet_Roles_FullAccess
DROP ROLE aspnet_Roles_BasicAccess
DROP ROLE aspnet_Roles_ReportingAccess
DROP ROLE aspnet_WebEvent_FullAccess
DROP ROLE aspnet_Profile_BasicAccess

Thursday 9 January 2014

GeoLocation - Get Country of IP Address

Sometimes in projects we build we need to add a level of localization. E.g. Some customers access sites from the UK and others from Ireland. Each site offers a different selection of products and the only way to truly ensure a customer can see the correct products for their location is to create a user account.

Although the Mechanism for creating a user account is simple for browsing a website - Customers do find this confusing as one minute the products are there and the next they are not.

So In this case we need to identify the Country by IP, There are many reasons why this could potentially fail however on the whole it catches most potential customers.

First I create a link to http://freegeoip.net/json/ and I append the IP Address onto the end of this.


private static readonly string GeolocationUrl = "http://freegeoip.net/json/212.58.244.66";


From this we get a JSON String that gives us the information pertaining to this IP Address.

{"ip":"212.58.244.66","country_code":"GB","country_name":"United Kingdom","region_code":"N7","region_name":"Surrey","city":"Tadworth","zipcode":"","latitude":51.2833,"longitude":-0.2333,"metro_code":"","area_code":""}


This indeed gives us a Country Code and Country Name from which we can parse and use for our application. The following method below is sufficient to return us an object called 'IpInformationLocation' The 'IpInformationLocation' object is rather simple, Its an object that we can use to build our data.

[Serializable]
public class IpLocationInformation
{
    [DefaultValue("")]
    public string IpAddress { get; set; }

    [DefaultValue("")]
    public string CountryCode { get; set; }

    [DefaultValue("")]
    public string CountryName { get; set; }

    [DefaultValue("")]
    public string RegionCode { get; set; }

        [DefaultValue("")]
        public string RegionName { get; set; }

        [DefaultValue("")]
        public string City { get; set; }

        [DefaultValue("")]
        public string ZipCode { get; set; }

        [DefaultValue("")]
        public string Latitude { get; set; }

        [DefaultValue("")]
        public string Longitude { get; set; }

        public IpLocationInformation() { }

        public IpLocationInformation(string json)
        {
            JObject jObject = JObject.Parse(json);

            //JToken jDataBlock = jObject[""];

            IpAddress = jObject["ip"].ToString();

            CountryCode = jObject["country_code"].ToString();
            CountryName = jObject["country_name"].ToString();
            RegionCode = jObject["region_code"].ToString();
            RegionName = jObject["region_name"].ToString();
            City = jObject["city"].ToString();
            ZipCode = jObject["zipcode"].ToString();
            Latitude = jObject["latitude"].ToString();
            Longitude = jObject["longitude"].ToString();
        }
        public override string ToString()
        {
            string theReturn = string.Format("@\n\n" +
                                             "IP Address: {0}\n" +
                                             "Country Code: {1}\n" +
                                             "Country Name: {2}\n" +
                                             "RegionCode: {3}\n" +
                                             "City: {4}\n" +
                                             "ZipCode: {5}\n" +
                                             "Latitude: {6}\n" +
                                             "Longitude: {7}\n\n", new object[] {IpAddress, CountryCode, CountryName, RegionCode, City, ZipCode,Latitude,Longitude});
            return theReturn;
        }
    }


We then create a method that uses the website above, Adds and IP Address then generates an IpLocationInformation object. We do this like so.

public IpLocationInformation GetLocationByIp(string ipAddress)

        {

            try

            {

                string formattedUri = string.Format(CultureInfo.InvariantCulture, GeolocationUrl, ipAddress);



                var webRequest = GetWebRequest(formattedUri);

                var response = (HttpWebResponse)webRequest.GetResponse();



                var jsonResponse = string.Empty;



                var stream = response.GetResponseStream();

                if (stream != null)

                {

                    var reader = new StreamReader(stream);



                    jsonResponse = reader.ReadToEnd();

                }



                var ipLocation = new IpLocationInformation(jsonResponse);



                return ipLocation;

            }

            catch (Exception)

            {

                throw new WebException("There was a problem processing this Request.  Please Check the Information which you are passing.");

            }

        }


After this we are able to use the method to deduce the location of the calling IP Address which can then give the user a customized version of the site.