Encrypting Url parameters with DES

When reading and validating URL parameters you probably came across the situation that you wanted to hide some values for security reasons. Such a situations happen very often eg. when confirming email address of an user by sending validation link or by validating payment callback etc.

One of the solutions is to encrypt Url parameters using DES algorithm. DES it’s a symmetric algorithm that allows you to encrypt and decrypt values using shared public key. It is advisable to change public key from time to time for security reasons.

Below are two helper methods needed to encrypt and decrypt values:

    /// <summary>
    /// Encrypts an string using provided public key (DES)
    /// </summary>
    /// <param name="stringToEncrypt">String to be encrypted</param>
    /// <param name="sEncryptionKey">Public key</param>
    /// <returns>string</returns>
    public static string DES_encrypt(string stringToEncrypt, string sEncryptionKey)
    {
     if (stringToEncrypt.Length <= 3) { throw new Exception("Invalid input string"); }

     byte[] key = { };
     byte[] IV = { 10, 20, 30, 40, 50, 60, 70, 80 }; //defining vectors
     byte[] inputByteArray;
     key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
     using (var des = new DESCryptoServiceProvider())
     {
        inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                return Convert.ToBase64String(ms.ToArray());
            }
        }
      }
   }

and

    /// <summary>
    /// Decrypts an string using provided public key (DES)
    /// </summary>
    /// <param name="stringToDecrypt">String to be decrypted</param>
    /// <param name="sEncryptionKey">Public key</param>
    /// <returns>string</returns>
    public static string DES_decrypt(string stringToDecrypt, string sEncryptionKey)
    {
     if (stringToDecrypt.Length <= 3) { throw new Exception("Invalid input string"); }

     byte[] key = { };
     byte[] IV = { 10, 20, 30, 40, 50, 60, 70, 80 };//defining vectors
     byte[] inputByteArray = new byte[stringToDecrypt.Length];
     key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
     using (var des = new DESCryptoServiceProvider())
     {
        inputByteArray = Convert.FromBase64String(stringToDecrypt.Replace(" ", "+"));
        using (var ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(key, IV), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                var encoding = Encoding.UTF8;
                return encoding.GetString(ms.ToArray());
            }
        }
     }
   }

In real life scenario when sending validation email we are simply encrypting our parametrized string the way shown bellow:

  var urlParam = txtEmail.Text + ";" + userID + ";" + DateTime.Now.ToString();

  var encryptedParam = Encryption.DES_encrypt(urlParam, "12345678");

  //send confirmation email with link: https://www.myadress.com/validate.aspx?sid=encryptedParam

When someone clicks the link and comes to our page we need to decrypt values and read the data.

   var encryptedParam = Request["sid"];

   var decryptedParam = Encryption.DES_decrypt(encryptedParam, "12345678");

   var email = decryptedParam.Split(';')[0];
   var userID = decryptedParam.Split(';')[1];
   var dateSent = DateTime.Parse(decryptedParam.Split(';')[2]);

As you probably have noticed, we use same public key to encrypt and decrypt values. In our situation the public key is safe because it is only stored on our server and is not being sent across the network.

For the above functions to be fully functional you need implement basic validation. It is also a good practice to add timestamp date to encrypted string so we can ensure the data was sent within defined time frame, lets say within last 5 minutes. After that the data will expire and wont be accepted by our application.

DES it’s quite save and efficient algorithm that you can use in your daily programming. It should be suitable in most case scenarios, unless you are building banking system 🙂

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Creating MVC3 Custom View Engine

MVC it’s so great and flexible framework that even lets you create your own custom view engine if you need to replace Razor’s default rendering. You will probably not need this but we I will show you how to do it.

In our example we simply display all view data that are available during http request. Lets create our debug class that inherits from IView interface. In the Render function we simply use textwriter to display request data. The code looks as follows:

 public class DebugDataView : IView
 {
    public void Render(ViewContext viewContext, TextWriter writer)
    {
        Write(writer, "---Routing Data---");
        foreach (string key in viewContext.RouteData.Values.Keys)
        {
            Write(writer, "Key: {0}, Value: {1}",
            key, viewContext.RouteData.Values[key]);
        }

        Write(writer, "---View Data---");
        foreach (string key in viewContext.ViewData.Keys)
        {
            Write(writer, "Key: {0}, Value: {1}", key,
            viewContext.ViewData[key]);
        }
    }

    private void Write(TextWriter writer, string template, params object[] values)
    {
        writer.Write(string.Format(template, values) + "<p/>");
    }
}

Next we need to create our debug view engine class that inherits from IViewEngine interface. In FindView function, if our view name is found, we simply apply our own view style by passing in the instance of DebugDataView class that we have implemented earlier.

 public class DebugDataViewEngine : IViewEngine
 {
    public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        if (viewName == "DebugData")
        {
            return new ViewEngineResult(new DebugDataView(), this);
        }
        else
        {
            return new ViewEngineResult(new string[] { "Debug Data View Engine" });
        }
    }

    public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
    {
        return new ViewEngineResult(new string[] { "Debug Data View Engine" });
    }

    public void ReleaseView(ControllerContext controllerContext, IView view)
    {
        // no action here
    }
}

The last step is to register our custom engine in the Application_Start() function.

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        ViewEngines.Engines.Add(new DebugDataViewEngine());

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

Download the sample below to see how it works.
CustomViewEngine

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Custom Tree View Control

When using default asp.net Tree View control there is always been a problem to get the proper styling at the node level. Example of that is trying to set an node font weight to bold.

The simplest solution is to create custom tree view node that inherits from default TreeNode class.

  public class CustomTreeNode : TreeNode
  {
  }

When overriding RenderPreText method in that class we can change default rendering of the tree node text the way we want. We do it by adding text attributes using htmltextwriter. Below is example of that.

 protected override void RenderPreText(HtmlTextWriter writer)
 {
      writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
      writer.RenderBeginTag(HtmlTextWriterTag.Span);
      base.RenderPreText(writer);
  }

Here is complete working example of the custom tree view node.

 public class CustomTreeNode : TreeNode
    {
        public CustomTreeNode() : base() { }
        public CustomTreeNode(TreeView owner, bool isRoot) : base(owner, isRoot) { }

        private string _cssClass;
        public string CssClass
        {
            get { return _cssClass; }
            set { _cssClass = value; }
        }

        protected override void RenderPreText(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
            writer.RenderBeginTag(HtmlTextWriterTag.Span);
            base.RenderPreText(writer);
        }

        protected override void RenderPostText(HtmlTextWriter writer)
        {
            writer.RenderEndTag();
            base.RenderPostText(writer);
        }
    }

    public class CustomTreeView : TreeView
    {
        protected override TreeNode CreateNode()
        {
            return new CustomTreeNode(this, false);
        }
    }

Example of use:

      var tn = new CustomTreeNode();
      tn.Text = "test";
      tn.Value = "1";
      tn.CssClass = "normalNode/boldNode";          
      treeView.Nodes.Add(tn);

    //and the css
    .normalNode
    {
	font-weight:normal;
    }
    
    .boldNode
    {
	font-weight:bold;
    }

I hope this article helped you to understand how we can change default control rendering.

custom-tree-node

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Remote Post utility

If you want to do an http post from code behind eg. to redirect to payment page it is sometimes useful to have an helper to be used throughout your application. Below is the simple class that does it’s job.

 public class RemotePost
{
    private NameValueCollection Inputs = new NameValueCollection();
    public string Url = "";
    public string Method = "post";
    public string FormName = "form1";

    public void Add(string name, string value)
    {
        Inputs.Add(name, value);
    }

    public void Post()
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.Write(@"<html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=iso-8859-1"">");
        HttpContext.Current.Response.Write(String.Format(@"</head><body onload=""document.{0}.submit()"">", FormName));
        HttpContext.Current.Response.Write(String.Format(@"<form name=""{0}"" method=""{1}"" action=""{2}"" >", FormName, Method, Url));
        int i = 0;
        while (i < Inputs.Keys.Count)
        {
            HttpContext.Current.Response.Write(String.Format(@"<input name=""{0}"" type=""hidden"" value=""{1}"">", Inputs.Keys[i], Inputs[Inputs.Keys[i]]));
            i += 1;
        }
        HttpContext.Current.Response.Write("</form>");
        HttpContext.Current.Response.Write("</body></html>");
        HttpContext.Current.Response.End();
    }
}

When using it you simply add your parameters in the button click event before doing post request.


public void btnPay_OnClick(object sender, EventArgs e)
 {
        RemotePost myremotepost = new RemotePost();
        myremotepost.FormName = "form1";
        myremotepost.Method = "post";
        myremotepost.Url = "https://.......";
        myremotepost.Add("id", "123");
        //.....
        //----
        /////////////////////////
        myremotepost.Post();
}

An alternative way to that is sample below. You may also want to set PostBackUrl of the clicked button to avoid user to see response page.

 public void Post()
    {
        string url = "post url";

        using (StringBuilder postData = new StringBuilder())
        {
            postData.Append("first_name=" + HttpUtility.UrlEncode(txtFirstName.Text) + "&");
            postData.Append("last_name=" + HttpUtility.UrlEncode(txtLastName.Text));

            //TO DO - do it for all Form Elements

            //////////////////////////////
            StreamWriter writer = null;

            using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url))
            {
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = postData.ToString().Length;
                try
                {
                    writer = new StreamWriter(request.GetRequestStream());
                    writer.Write(postData.ToString());
                }
                finally
                {
                    if (writer != null)
                        writer.Close();
                }
            }
        }

        Response.Redirect("RedirectPage");

    }
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Format DataTextField of the DropDownList

Some times there is a need to format DataTextField value of the DropDownList without changing the data source structure.
One of the ways to achieve this is to use LINQ by changing the property value “on the fly”. We just need to create the new structure that is being bound to the DropDownList.

   var userList = GetUsers();

   ddlUsers.DataSource = (from obj in userList
	       select new
		{
		  ID = obj.ID,
		  Name = string.Format("{0} {1} - £{2}", obj.Name, obj.SurName, obj.Balance)
		}).ToList();
                    
   ddlUsers.DataTextField = "Name";
   ddlUsers.DataValueField = "ID";
   ddlUsers.DataBind();              
 

This is quite handy when you are unsure if the text formatting will change in the future. Hope I helped you with this quick example 🙂

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Polymorphism in practice (C# sample)

One of the main principles of the Object Oriented Programming is the Polymorphism. This term simply means that an class can be used as more than one type through inheritance. It can have it’s own type, the base type or interface type it inherits from. In C# every type is polymorphic as the all types inherit from Object type.

Lets assume we are building an Internet store with the basket functionality. By creating base class and inheriting from it we get all properties from the base class plus the properties of the class that we are creating. By marking class as abstract we specify that this class cannot be instantiated and may serve only as a base class for other classes deeper in the system.

  public abstract class BasketBase
  {

  }

   public class Basket : BasketBase
   {

   }

By marking methods as a virtual in the base class, we can implement our own logic whenever we need it using override keyword in the underlying class.

   public abstract class BasketBase
   {
        public List<ProductItem> ProductList = new List<ProductItem>();
        public double Total = 0;
        public bool IsCheckedOut = false;
        public abstract void Checkout();
    }

    public class Basket : BasketBase
    {
        public override void Checkout()
        {
            if (base.IsCheckedOut) { throw new Exception("Check out has been already done!"); };
            ////////////

            foreach (ProductItem p in base.ProductList)
            {
                base.Total += p.ProductPrice * p.ItemCount;
            }

            base.IsCheckedOut = true;
        }
     }

When building advanced systems, Polymorphism gives you the chance to easily change the logic of existing methods by overriding it. It also makes your application cleaner by reusing amount of code needed to create properties in underlying classes.

I have included sample application of the Internet store with the basket and voucher functionality for you to do some testing.


basket.vouchers
Polymorphism-sample-app

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Skype Chat History Export using C# and Interop

Ever wanted to export Skype chat history to text or xml files? There is an solution for that as it seems that there is no such a option in new Skype version.

It is possible thanks to Skype Interop object which allows us to interact and extend the application functionality. In order to start we need to install that object on our machine (installation file is included at the bottom of this article) and add reference to it in our visual studio project.

skype-refence2

 

Next we need to instantiate the interop object and get the current logged in user. We also need to ensure that the Skype application is running, if not we need to start it up.

SKYPE4COMLib.Skype oSkype = new SKYPE4COMLib.Skype();
if (!oSkype.Client.IsRunning) oSkype.Client.Start(true, true);

var owner = oSkype.CurrentUser.FullName + " (" + oSkype.CurrentUser.Handle + ")";</pre>
Next we need to simply loop through all chats
1
foreach (SKYPE4COMLib.Chat oChat in oSkype.Chats)
{

and all chat messages for each member on our contact list

foreach (SKYPE4COMLib.ChatMessage oMessage in oChat.Messages)
{

In this place you can customize it; save it to database, xml files, do an action depending on the chat content etc.

foreach (SKYPE4COMLib.Chat oChat in oSkype.Chats)
{
    try
    {
        var name = oChat.Name;
        var description = oChat.Description;
        var members = new SortedList();
        foreach (SKYPE4COMLib.User oUser in oChat.Members)
        {
            members.Add(oUser.FullName + " (" + oUser.Handle + ")", null);
        }

        var filename = "\\chat";
        foreach (var m in members.Keys)
        {
            filename += " " + m;
        }
        filename = filename.Replace(owner, "").Replace("  ", " ");
        if (filename.Length > 100) filename = filename.Substring(0, 100);
        filename = filename.Trim() + ".txt";

        Console.WriteLine();
        Console.WriteLine("Chat File = " + filename);
        Console.WriteLine("With " + oChat.Messages.Count.ToString() + " Message(s)");

        filename = basePath + filename;

        var iMessageCount = oChat.Messages.Count;
        iCounter = 0;
        var messages = new StringBuilder(21000);
        foreach (SKYPE4COMLib.ChatMessage oMessage in oChat.Messages)
        {
            iCounter++;
            messages.Append(oMessage.Timestamp + "\t" + oMessage.FromDisplayName + "\t" + oMessage.Body + "\r\n");
            if (iCounter % 25 == 0) Console.Write(".");
            if (messages.Length > 20000)
            {
                System.IO.File.AppendAllText(filename, messages.ToString());
                messages = new StringBuilder(21000);
                GC.Collect();
            }
            if (iMessageCount - iCounter > 1000)
                if ((iMessageCount - iCounter) % 1000 == 0)
                {
                    Console.WriteLine("");
                    Console.Write((iMessageCount - iCounter).ToString() + " ");
                }
        }
        System.IO.File.AppendAllText(filename, messages.ToString());
        Console.WriteLine(" OK");
    }
    catch (Exception ex)
    {
        Console.WriteLine();
        Console.WriteLine("Error " + ex.Message);
        Console.WriteLine();
    }
}

The first time your application contacts Skype using Interop object, an Skype security message is displayed allowing to reject or access the Skype data.

skype-message

 

POST UPDATE!
If you are running x64 bit PC then you need to do following:

1. Register Skype interop using below command
C:\Windows\System32\regasm.exe "C:\Program Files (x86)\Common Files\Skype\Skype4COM.dll"

2. In Visual Studio you need to change target platform to x86

skype_x64

This works for me when running Skype version: 6.11.0.102

Enjoy!
SkypeChatHistoryExport

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

File helpers using LINQ

When dealing with files, it is useful to have standard set of helpers to be used that we can relay on. This is when LINQ comes in handy. In this article I will present you with some useful functions that you can use in your daily programming.

Simple operation should be simple. Hence, when getting the number of lines in the text file, one line of code is just enough.

 public static long GetNumberOfLines(string filePath)
 {
     return File.Exists(filePath) ? File.ReadAllLines(filePath).Count() : 0;
 }

Getting the biggest file in the folder is also very easy with LINQ

   public static string FindTheLargestFileInDirectory(string path)
    {
        return Directory.Exists(path) && Directory.GetFiles(path).Count() > 0 ? 
               Directory.EnumerateFiles(path).Select(i => new FileInfo(i))
               .OrderByDescending(i => i.Length).FirstOrDefault().FullName : null;
    }

Similar when getting all files with the size of less than 1 Kb

   public static IEnumerable<string> FindFilesLessThanOneKiloBytesInThisFolder(string path)
    {
        return Directory.Exists(path) && Directory.GetFiles(path).Count() > 0 ?  
             Directory.EnumerateFiles(path).Select(i => new FileInfo(i))
             .Where(i => i.Length < 1024).Select(i => i.FullName) : null;
    }

You can use this function if you need to get files created in last 7 days

   public static IEnumerable<string> FindAllFilesCreatedLessThanWeekAgo(string path)
   {
        return Directory.Exists(path) && Directory.GetFiles(path).Count() > 0 ? 
               Directory.EnumerateFiles(path).Select(i => new FileInfo(i))
               .Where(i => i.CreationTime > DateTime.Now.AddDays(-7))
               .Select(i => i.FullName) : null;
   }

And finally if you want to get the oldest file in the folder (common scenario when deleting old logs) you can try this

   public static string FindOldestFileInFolder(string path)
   {
        return Directory.Exists(path) && Directory.GetFiles(path).Count() > 0 ? 
               Directory.EnumerateFiles(path)
               .Select(i => new FileInfo(i))
               .OrderByDescending(i => i.LastAccessTime).FirstOrDefault()
               .FullName : null;
   }

If you want to compare two files and get identical lines this may be useful to you

   public static IEnumerable<string> FindIdenticalLinesInTwoFiles(string filePath1, string filePath2)
    {
        if (File.Exists(filePath1) && File.Exists(filePath2))
        {
            return File.ReadAllLines(filePath1).Where(i => !string.IsNullOrEmpty(i))
                   .Intersect(File.ReadAllLines(filePath2).Where(i => !string.IsNullOrEmpty(i)));
         }

       return null;
    }

When collecting system information this function may be useful as well. It simply gets all extensions of the files in the directory and counts number of files associated with them.

 public static Dictionary<string, int> ListAndCountTheNumberOfDifferentFileExtensions(string path) 
   {
       return Directory.EnumerateFiles(path)
              .Select(i => new FileInfo(i))
              .GroupBy(i => i.Extension)
              .OrderByDescending(i => i.Count())
              .ToDictionary(i => i.Key, i => i.Count());            
    }

As you can see using LINQ is so easy that allows you to focus more on the business problems and less on coding itself.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Using Html5 Local storage on mobile devices

In many situations there is a need to store something on the mobile device that can be later retrieved and reused. Typical situation is the offline state where device suddenly loosing internet connection.

To solve this problem we can use HTML5 local storage. It works on all mobile devices with the most popular browsers. Additionally, unlike the cookies the values are not being transmitted from device to the server on each request. They are also persistent across the pages.

In our example we will assume that user sends timesheet data from his mobile device (the files are running locally on the device).
When user sends the data, we store it in local storage trying to send it. If sending is not successful, we keep it in the storage. We also check if we can send the data every time user posts the new form.

 //when DOM is ready
 $(document).ready(function () {

    //try to post saved data every time someone loads page (silent mode)
    trySaveOfflineData(true);

    //if someone saved the form
    var id = getUrlVars()["UserID"];
 
    if (id != null) {
        
        //save in local storage first
        saveData();

        //post local storage data data
        trySaveOfflineData(false);
    }
});

We also need to check if local storage is supported on the mobile device.

 function supportsLocalStorage() {
    //check if device supports local storage
    try {
        return 'localStorage' in window && window['localStorage'] !== null;
    } catch (e) {
        return false;
    }
}

When user saves the data we simply read the values and concatenate it to the single string object. We will read this values later using generic handler in our standard asp.net application located on the remote server.

 function saveData() {
    //read url params from submitted form (we can also use post method instead)
    var userID = getUrlVars()["UserID"];
    var name = getUrlVars()["Name"];
    var comments = getUrlVars()["Comments"];
    var hours = getUrlVars()["Hours"];
    var overtime = getUrlVars()["Overtime"];
    var job = getUrlVars()["Job"];

    var idKey = 'timesheet.' + userID;//set the unique key making sure it belongs to us
    var obj = userID + "|" + name + "|" + comments + "|" + hours + "|" + overtime + "|" + job;

    //save object in local storage
    localStorage.setItem(idKey, obj);

    return true;
}

Every time user loads the page we read values from the local storage and try to post it to our web application. If he gets internet connection we should be able to push our storage data to the server.

 function trySaveOfflineData(silent) {
    // check all keys in local storage
    for (var key in localStorage) {
        
        //check if it our data
        if (key.search('timesheet.') >= 0) {

            var dataObj = localStorage[key]; // get object

            //post it to the server
            postData(SERVER_URL, dataObj, silent);

            //delete item from local storage
            localStorage.removeItem(key);
        }
    }
}

When posting the data we simply use Jquery post method. Next, we read the response from the server as a string and display messages if necessary.

 function postData(url, dataObj, silent) {
    //use Jquery post and send object as a param timesheetObj
    $.post(url, { timesheetObj: dataObj },
                             //get response
                             function (data) {
                                 if (data == "OK") {
                                     if (!silent) { alert("Data has been sent!"); }
                                     return;
                                 }
                                 //if not supports local storage display warning
                                 if (!supportsLocalStorage()) {
                                     if (!silent) { alert("offline mode not supported!"); }
                                     return;
                                 }
                                 //if we got here - it has to be an error 🙂
                                 if (!silent) { alert("Error occurred: " + data); }
                             });
 }

On the server side we use generic handler to process the request. We also need to set headers to avoid Cross-site HTTP request errors.

  public void ProcessRequest(HttpContext context)
  {
        // this is to avoid following error: XMLHttpRequest cannot load https://localhost:58017/WebSite/send.ashx. 
        // Origin https://localhost:58078 is not allowed by Access-Control-Allow-Origin.
        context.Response.AppendHeader("Access-Control-Allow-Origin", "*");  
        context.Response.ContentType = "text/plain";

        try
        {
            var data = context.Request["timesheetObj"];
            var timesheet = data.Split('|');

            var userID = timesheet[0];
            var name = timesheet[1];
            var comments = timesheet[2];
            var hours = timesheet[3];
            var overtime = timesheet[4];
            var job = timesheet[5];
            
            //check and save the data here

        }
        catch (Exception ex)
        {
            context.Response.Write(ex.Message); return;
        }

        context.Response.Write("OK");
    }

Solution I described it’s just a test sample that needs to be converted using PhoneGap before going into production. PhoneGap simply wraps html elements to get desired look on the device. We would also need to apply security measures to avoid fake or duplicated requests etc.

In general I this this is good alternative to creating mobile solution that works only on one platform.

I have included working example below for you tests. Happy coding 🙂
Html5-LocalStorage

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Extension methods in C#

Extension methods enable you to add your own methods to already existing system types without deriving from those types. Extension methods are always static but they are called as a instance methods on the extended types. We can extend types like string, double, DateTime etc. as well as LINQ queries which already are extensions of IEnumerable type.

Extended types can be used as a helper methods that you can compile and use in all your projects.

Lets start with the simple string extensions. First example simply checks if string has a value. The second one strips html tags from the string.

    /// <summary>
    /// Determines whether this instance of string is not null or empty.
    /// </summary>
    public static bool HasValue(this string text)
    {
        return !string.IsNullOrEmpty(text);
    }

    /// <summary>
    /// Strips html tags from the string
    /// </summary>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>", string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty);
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty);
    }   

Similar is with the double extensions

    /// <summary>
    /// Rounds the value to last 10s
    /// </summary>
    public static double RoundOff(this double i)
    {
        return ((double)Math.Round(i / 10.0)) * 10;
    } 

The sample below is very useful when displaying dates. It displays friendly string with the time left to an event, it extends DateTime type.

 public static string ToDateLeftString(this DateTime input)
    {
        var oSpan = DateTime.Now.Subtract(input);
        var TotalMinutes = oSpan.TotalMinutes;
        var Suffix = " ago";

        if (TotalMinutes < 0.0)
        {
            TotalMinutes = Math.Abs(TotalMinutes);
            Suffix = " from now";
        }

        var aValue = new SortedList<double, Func<string>>();
        aValue.Add(0.75, () => "less than a minute");
        aValue.Add(1.5, () => "about a minute");
        aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
        aValue.Add(90, () => "about an hour");
        aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
        aValue.Add(2880, () => "a day"); // 60 * 48
        aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
        aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
        aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 
        aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
        aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));

        return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
    } 

The last example extends the IEnumerable type so we are actually adding a new LINQ function.

    /// <summary>
    /// Selects the item with maximum of the specified value.
    /// </summary>
    public static T WithMax<T, TKey>(this IEnumerable<T> list, Func<T, TKey> keySelector)
    {
        return list.OrderByDescending(i => keySelector(i)).FirstOrDefault();
    } 

When testing above methods you will get following results

  static void Main(string[] args)
    {
        //DateTime extended method
        var myDate = DateTime.Now.AddDays(7);
        var dateLeft = myDate.ToDateLeftString(); //result: "6 days from now"

        //System.String extended method
        var myNoHtmlString = "<br><b>test</b>".HtmlStrip(); //result: "test"

        //or 
        var hasStringValue = "test string".HasValue(); //result: true

        //System.Double extension
        double myTo10sRoundedValue = (66.3).RoundOff(); //result: 70

        //Linq extensions
        List<int> list = new List<int>() { 1, 2, 3 }; 
        var max = list.WithMax(i => i); //result: 3
    }

I have included sample project below so you can do some testing yourself.
ExtensionMethods

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...