Implementing MVC3 Custom Model Binders

MVC model binders simply map Http browser requests to model objects. Normally if action invoker is unable to find the proper binder of the provided type, it uses built-in binder class: DefaultModelBinder. Default model binder is using following sources to bind to model object: Request.Form, RouteData.Values, Request.QueryString, Request.Files. The search for values is also done in same order.

We can include and exclude bindings for some object properties in action method or in class attribute.

 public ActionResult Create([Bind(Include="FirstName, LastName")] Client client) {

 //or in our class
 [Bind(Exclude="IsApproved")]
 public class Client {

In our example we will bind the model manually. This gives us more controls on how the model objects are instantiated and helps if we are using dependency resolver.

 [HttpPost]
  public ActionResult Edit(int id, FormCollection collection)
  {
        try
        {
            // TODO: Add update logic here
            //client client = (client)DependencyResolver.Current.GetService(typeof(client));
            var client = new Client();

            UpdateModel(client, collection);

            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

Below is our custom model binder implementation. Please note that the binder class needs to inherit from IModelBinder interface. In the example, we simple check if model exists or use dependency resolver to provide one. Next we are getting prefixes and values from BindingContext.ValueProvider property, that gives us all consolidates value providers we can read from. Please note that we didn’t include any validation logic.

  public class ClientModelBinder : IModelBinder
  {

   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // check if model to update exists and create one if not
        Client model = (Client)bindingContext.Model ?? (Client)DependencyResolver.Current.GetService(typeof(Client));

        // check if the value provider has the required prefix
        bool hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);

        string searchPrefix = (hasPrefix && !string.IsNullOrEmpty(bindingContext.ModelName)) ? bindingContext.ModelName + "." : "";

        // populate the fields of the model object
        model.ClientId = int.Parse(GetValue(bindingContext, searchPrefix, "ClientId"));
        model.FirstName = GetValue(bindingContext, searchPrefix, "FirstName");
        model.LastName = GetValue(bindingContext, searchPrefix, "LastName");
        model.BirthDate = DateTime.Parse(GetValue(bindingContext, searchPrefix, "BirthDate"));
        model.IsApproved = GetCheckedValue(bindingContext, searchPrefix, "IsApproved");
        model.Role = (Role)Enum.Parse(typeof(Role), GetValue(bindingContext, searchPrefix, "Role"));

        return model;
    }
 }

Next step is to register our custom binder. We can do it either in the global file or by giving attribute to our Client class.

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

        ModelBinders.Binders.Add(typeof(Client), new ClientModelBinder());

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

  //or
  [ModelBinder(typeof(ClientModelBinder))]
  public class Client
   {

You can also implement your own model binder provider which is very useful when handling multiple custom class binders.

 public class CustomModelBinderProvider : IModelBinderProvider 
 {
   public IModelBinder GetBinder(Type modelType) 
   {
      //return or apply the switch with other model type binders
      return modelType == typeof(Client) ? new ClientModelBinder() : null;
   }
 }

 //you can register provider in global app start method
 ModelBinderProviders.BinderProviders.Add(new CustomModelBinderProvider());

I have included application sample, so you can test how it works by setting the break point in the binding function and see how the model values are being retrieved.
CustomModelBinder

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

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...

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...