Technology is no place for fidelity

I just read an article titled 'Don't Fall in Love With Your Technology' and it got me thinking.

As a developer, I pose the question 'Is there anything wrong with falling in love with particular technologies?'

Probably.

In order for your relationship with your selected technology stack to work, you have to nurture it, practice it, live it and work with it. Take it out of the office and use it at home on a rainy Sunday afternoon, push it to its limits, explore it fully, however also understand it's important to be able to accept when it's no longer appropriate to use a particular technology.

The problem with falling in love with your technology is that many people I've met seem to do it 'head over heels'.

Don't be faithful when it comes to technology. Take a new one out for a spin every so often. You never know what you're missing and if you don't, you may fall behind.  If you don't like it, don't use it! Most importantly, keep your mind open.

It's difficult enough staying up to date in this industry without becoming stagnant through loyalty to a particular technology or stack. I'd bet that the tech you're using today will one day become a 'remember the days I used to use....' thought.

View Post (495) or Add Comments (1)


ASP.NET MVC 4 - Bundling and Minification of JavaScript and CSS

I usually use a combination of JSMin and the Telerik script manager to minify my JavaScript and CSS, however the ASP.NET MVC 4 beta has built in minification, which reduces the number of requests and general payload size, resulting in faster and better performing applications.

This feature allows you can create custom bundles where you specify the resource name and order of your stylesheets and JavaScript files.

Introducing ASP.NET MVC 4 BundleTables

Upon creating a new project in ASP.NET MVC 4, you'll notice that your default _Layout.cshtml file will reference System.Web.Optimization and BundleTable.Bundles in its head.

According to Microsoft, these references are for the beta and will be accessed via a helper in the RTM release, expected sometime next quarter.

<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")" rel="stylesheet"    type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>

If you look at the actual source code in the browser, you will see these get rendered as:

<link href="/Content/css?v=x" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/css?v=y" rel="stylesheet" type="text/css" />
<script src="/Scripts/js?v=z"></script>

The CSS and JavaScript files in this project are minified and compressed and the querystring parameter, v, is a hash of the current files being served. This will change when you alter your .js and .css files.

View Post (1514) or Add Comments (2)


Getting started with github

I've just started using git/github and have summarised below (for my own reference) a few of the commonly used git commands. I haven't included setting up your git client as this is well documented on github's help portal.

Setting up a git repository for an existing project

To initialise the git repository in the current directory

$ git init

Create a new file named README

$ touch README

Add README file to the repository

$ git add README

Add all files in the directory to the repository

$ git add *

Commit to your local repository

$ git commit -m 'first commit'

Commiting changes locally

Summarise changes since your last commit

$ git diff

Commit your changes to your local git repository

$ git commit -a -m "whatever"

or to discard the changes to your local git repository

git checkout -f

Commiting to github (First time)

Add the remote origin to the local git repository. Do this once per repository.

$ git remote add origin git@github.com:username/repo.git

Commiting to github (Subsequent Commits)

Send your commit to GitHub

$ git push origin master

New files to add?

Add any new files since your last update

$ git add *

Getting changes from your remote repository

To update any changed files from the server to your local repository, if you are working from more than one machine, for example

$ git pull

Deleting

To delete a local branch

$ git branch -d 2012.1-stable

To delete a remote branch

$ git push origin :branch

Checking out a branch

To check out a branch

$ git checkout branch

Cloning

Checking out a project when you don't have a local copy

$ git clone http://github.com/user/repo.git
$ git checkout -b 2012.1-stable origin/2012.1-stable 

Two great sites are Git - SVN Crash Course or an alternative and github help resourses. I'm using Git for Windows.

View Post (1012) or Add Comments (29)


Design pattern for ASP.NET MVC 3 application using repository pattern

Below is an example of how I typically implement the repository pattern in an ASP.NET MVC 3 project when using Entity Framework.

Model (Address.cs)

  [Bind(Include = "Id,Address")]
  [MetadataType(typeof(Address_Validation))]
  public partial class Address {}
  public class Address_Validation
{ //validation here }

Repository Interface (IAddressRepository.cs)

public interface IAddressRepository
  {
void Delete(Address u);
void Save();
void Add(Address b);
Address GetAddressById(int intAddressId);
}

Repository class (AddressRepository.cs)

public class AddressRepository : IAddressRepository 
{
private myEntities db = new myEntities();
public Address GetAddressById(int intAddressId)
{
return db.Addresses.FirstOrDefault(d => ((d.Address_ID == intAddressId)))
}
public void Delete(Address u)
{
db.Addresses.DeleteObject(u);
}
public void Save()
{
db.SaveChanges();
}
public void Add(Address b)
{
db.AddToAddresses(b);
db.SaveChanges();
}
}

Controller (AddressController.cs)

  public class AddressController : Controller
{ private IAddressRepository _addressRepository { get; set; } protected override void Initialize(RequestContext requestContext) {

if (_addressRepository == null)
{
_addressRepository = new AddressRepository();
}
base.Initialize(requestContext);
}
[AcceptVerbs(HttpVerbs.Post)] // Example..
public ActionResult _AddressInsert(AddressPartial objItem)
{
try
{ var objAddress = new Address
{
AddressTypeID = objItem.AddressTypeID,
...
} _addressRepository.Add(objAddress); _addressRepository.Save(); } }

Moving IContactRepository to a IRepository<T> interface would avoid code repetition and allow you to share the interface between all your repositories.

View Post (1568) or Add Comments (2)


Pre-generating views to improve query performance in Entity Framework

If you have used .NET Entity Framework, there’s a chance you will have run into performance issues when first loading your application.  One way to reduce this overhead is by pre-generating your view metadata as per this Microsoft guide.

I had a few problems using this resource so have prepared this step-by-step guide on how to pre-generate your views in EF 4.0.

Step 1: Change processing type for your .edmx model

Locate your model and open it in the designer.  Select “Copy to Output Directory” for the “Metadata Artefact Processing” option. This will result in .ssdl, .csdl and .msl files appearing in your output directory.  During debug, this will be bin/debug.

Step 2: Set up a pre-build event

Set up a pre-build event in your project by right clicking the project name, clicking properties and navigating to Build Events.  In the “Pre Build” box, include the following all on one line, replacing DataModel with the name of your model.

"%windir%\Microsoft.NET\Framework\v4.0.30319\EdmGen.exe" /mode:ViewGeneration "/inssdl:$(TargetDir)DataModel.ssdl" "/incsdl:$(TargetDir)DataModel.csdl" "/inmsl:$(TargetDir)DataModel.msl" "/outviews:$(ProjectDir)DataModel.Views.cs" /nologo /language:CSharp

Step 3: Set up post-build event

Next, build your project and you’ll see three files in your output directory (bin/debug).  We can add these to the project by creating a post-build event and using XCOPY to copy these to the root of your project.

XCOPY "$(TargetDir)DataModel.csdl" "$(ProjectDir)" /R /Y 
XCOPY "$(TargetDir)DataModel.ssdl" "$(ProjectDir)" /R /Y 
XCOPY "$(TargetDir)DataModel.msl" "$(ProjectDir)" /R /Y

Step 4: Include files in your project

Build the project which contains your model and you should see the following files in root directory of your project

  • DataModel.Views.cs
  • DataModel.csdl
  • DataModel.ssdl
  • DataModel.msl

Include all these files in your project via Show All Files > Right Click > Include In Project

Step 5: Set as embedded resources

Include DataModel.csl, DataModel.ssdl, DataModel.msl as an embedded resourcees in your project by clicking on the file and selecting "Embedded Resource" as your build action in the properties window.

Step 6: Update your web.config/app.config connection string

Update your connection string and you’re ready to go. Mine looks like this.  Be sure to use fully qualified names for your resources.
<add name="projectEntities" connectionString="metadata=res://*/Project.EF.DataModel.csdl|res://*/ Project.EF.DataModel.ssdl|res://*/ Project.EF.DataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=xxx.xxx.xxx.xxx;Initial Catalog=xxx;Persist Security Info=True;User ID=xxx;Password=xxx;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient"/>

If you receive, “Unable to load the specified metadata resource”, the path to your model in your configuration file is probably wrong.

View Post (623) or Add Comments (3)


Using regular expressions to get initials from a string in C#

Here is a really simple string extension to help you get initials from a string in C#

    public static string ToInitials(this string str)
    {
      return Regex.Replace(str, @"^(?'b'\w)\w*,\s*(?'a'\w)\w*$|^(?'a'\w)\w*\s*(?'b'\w)\w*$", "${a}${b}", RegexOptions.Singleline)
    }

Here's a breakdown on what the expression is doing:

  • ^ matches beginning of the string
  • (?'b'\w) captures first character of a word and stores in in 'b'
  • \w* matches the rest of the name
  • , matches a comma
  • \s* matches > 0 spaces
  • (?'a'\w)\w* matches the second part of the name capturing the first letter into 'b'
  • $ matches end of string
  • | or the alternate pattern w ithout the ,
  • Notice the 'a' and 'b' are swapped

There are more handy string extensions on 'String Extension Collection for C#'

View Post (530) or Add Comments (16)


Access your Nike+ run data using C# and .NET

Here's a really simple way to use your Nike+ run data on your own website using C#.

Firstly, get your Nike+ ID and test out your feed by pointing your browser to the Nike+ run list API URL as demonstrated below. You can find your unique ID using the instructions listed in this post.  It's worth noting that older accounts have a numeric ID, while newer subscribers have a GUID-like string like mine.

http://nikerunning.nike.com/nikeplus/v1/services/widget/get_public_run_list.jsp?userID=14fa3afc-8687-47ef-9899-75e8d090284d

If, after requesting this URL, you can see your run data in XML format, the 'share more' setting is already enabled in Nike+.  If not, you either have the wrong ID or you need to make your profile data public. You can do this within the privacy options within the Nike+ web application.

Here's a C# class I wrote to read the XML data into a strongly typed object called RunViewModel, consisting of 'summary' and 'run list' objects:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Net;

namespace com.kewney.examples.nikeplus
{
    
    public class RunViewModel
    {
        public List Runs { get; set; }
        public Summary Summary { get; set; }
    }

    public class Run
    {
        public DateTime startTime { get; set; }
        public float distance { get; set; }
        public int duration { get; set; }
        public DateTime syncTime { get; set; }
        public float calories { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public string howFelt { get; set; }
        public string weather { get; set; }
        public string terrain { get; set; }
        public string intensity { get; set; }
        public string gpxId { get; set; }
        public string equipmentType { get; set; }
        public string durationDesc
        {
            get
            {
                return TimeSpan.FromSeconds(duration / 1000).ToReadableString();
            }
            set { }
        }
         
    }
    public class Summary
    {
        public int runs { get; set; }
        public float distance { get; set; }
        public int runDuration { get; set; }
        public float calories { get; set; }
        public int duration { get; set; }
    }

    public static class RunMethods
    {

        private static string url = "http://nikerunning.nike.com/nikeplus/v1/services/widget/get_public_run_list.jsp";

        /// 
        /// Public method to obtain run data
        /// 
        /// Nike+ ID
        /// Run view model, containing run list and summary
        public static RunViewModel GetRuns(string id)
        {
            return new RunViewModel
            {
                Runs = GetRunList(id),
                Summary = GetSummaryInfo(id)
            };
        }

        private static List GetRunList(string id)
        {
            XmlReaderSettings xrs = new XmlReaderSettings();
            xrs.XmlResolver = new XmlUrlResolver();
            xrs.ValidationType = ValidationType.DTD;
            try
            {
                using (XmlReader xtr = XmlTextReader.Create(string.Format("{0}?userID={1}", url, id), xrs))
                {
                    XDocument xd = XDocument.Load(xtr);
                    return (from entry in xd.Descendants().Where(x => x.Name == "run")
                            select new Run
                            {
                                startTime = (DateTime)entry.Element("startTime"),
                                distance = (float)entry.Element("distance"),
                                duration = (int)entry.Element("duration"),
                                syncTime = (DateTime)entry.Element("syncTime"),
                                calories = (float)entry.Element("calories"),
                                name = (string)entry.Element("name"),
                                description = (string)entry.Element("description"),
                                howFelt = (string)entry.Element("howFelt"),
                                weather = (string)entry.Element("weather"),
                                terrain = (string)entry.Element("terrain"),
                                intensity = (string)entry.Element("intensity"),
                                gpxId = (string)entry.Element("gpxId"),
                                equipmentType = (string)entry.Element("equipmentType")
                            }).OrderByDescending(x => x.startTime).ToList();
                    xtr.Close();
                }
            }
            catch (WebException ex)
            {
                return new List();
            }
        }
        private static Summary GetSummaryInfo(string id)
        {
            XmlReaderSettings xrs = new XmlReaderSettings();
            xrs.XmlResolver = new XmlUrlResolver();
            xrs.ValidationType = ValidationType.DTD;
            try
            {
                using (XmlReader xtr = XmlTextReader.Create(string.Format("{0}?userID={1}", url, id), xrs))
                {
                    XDocument xd = XDocument.Load(xtr);
                    return (from entry in xd.Descendants().Descendants("runListSummary")
                            select new Summary
                            {
                                runs = (int)entry.Element("runs"),
                                distance = (float)entry.Element("distance"),
                                runDuration = (int)entry.Element("runDuration"),
                                calories = (float)entry.Element("calories"),
                                duration = (int)entry.Element("duration")
                            }).FirstOrDefault();
                    xtr.Close();
                }
            }
            catch (WebException ex)
            {
                return new Summary();
            }
        }
    }
}

Here's how to use the data:

RunListViewModel objMyRuns = BlogMVC.Models.RunMethods.GetRuns("14fa3afc-8687-47ef-9899-75e8d090284d")

From here, you can look through your run list and use the objMyRuns.Summary.Item to access the summary data

If you're wondering what the string extension ToReadableString() looks like, here it is:

 public static string ToReadableString(this TimeSpan span)
    {
        string formatted = string.Format("{0}{1}{2}{3}",
            span.Days > 0 ? string.Format("{0:0}d ", span.Days) : string.Empty,
            span.Hours > 0 ? string.Format("{0:0}h ", span.Hours) : string.Empty,
            span.Minutes > 0 ? string.Format("{0:0}m ", span.Minutes) : string.Empty,
            span.Seconds > 0 ? string.Format("{0:0}s", span.Seconds) : string.Empty);

        if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2);

        return formatted;
    } 

Have fun and here is an example of it in use.

Additional Information: More URLs from the Nike+ API

I haven't included any tutorial information on the other functionality of the other API URLs, but have listed them below for you to test.

URL Description
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/generate_pin.jhtml?login=&password= Authenticates the user and places a cookie on their system for later use.
http://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_user_data.jhtml Obtains data about the user (e.g. name, gender, country)
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/goal_list.jhtml List the goals of the selected user
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/run_list.jhtml Lists the users runs and statistics, as used in this post
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_run.jhtml?id= A detailed view of the run, including numbers from the run list
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/get_challenges_for_user.jhtml Lists the user's challenges
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/personal_records.jhtml Lists the user's personal records

View Post (1487) or Add Comments (13)


Abstract classes vs. interfaces in C#

Introduction

Functionality in abstract classes and interfaces in C# is fairly similar, however use of each has supporting and opposing arguments. This article discusses the theoretical aspects of these programming concepts backed up with a working example in C# at the end of this post.

There are three areas to consider when deciding which to implement for a specific purpose within your project:

1. Inheritance

Simply put, a class can only inherit from one other class. If you inherit from an abstract class, more can be achieved. Conversely, a class can implement an unlimited number of interfaces as well as still being able to inherit from a base class.

2. Structure

Interfaces offer a greater degree of design flexibility because they can be used by any class regardless of type.

3. Versioning

As mentioned, an abstract class can contain interfaces and also have the ability to inherit from base classes. This makes version control an awful lot easier.

Changing an interface will result in all classes which depend on it breaking. Once this has been used, its contents and functionality is permanant. Code based on interfaces can only be improved or extended by added new interfaces.


Scenarios where an abstract class is suitable

  • The class you're developing will be distributed to many other developers or clients or you're creating an API.
  • You wish to create a common base class for a family of types.
  • You want to provide a default behaviour

Scenarios where an interface is suitable

  • You're creating a class which will be used in an internal project which won't be shared with a large number of developers or used in an API
  • You're looking to provide polymorphic behaviour without subclassing or you want a specific type to display multiple behaviours.

If you are looking for a more detailed answer to this question, what is difference between abstract class and interface, then visit this link for further reading.


Example

Here is an example using code.  I've created a Product abstract class and an IProduct interface.  I've commented throughout the code and included a test class at the end. 

In the test class, the DisplayPrice method when using the abstract class displays the product price for staff, applying no markup, whereas it shows the full retail price when the customer interface is called. 

The Abstract Class 'Product'

namespace com.kewney.examples.abintex
{
    /// 
    /// Summary for Product
    /// 
    public abstract class Product
    {
        /// 
        /// Define Fields
        /// 
        protected int pId;
        protected String pName;
        protected String pDescription;
        protected decimal pCost;

        /// 
        /// properties
        /// 

        public abstract int ID
        {
            get { }
            set { }
        }

        public abstract String ProductName
        {
            get { }
            set { }
        }

        public abstract String ProductDescription
        {
            get { }
            set { }
        }

        public abstract decimal ProductBuyPrice
        {
            get { }
            set { }
        }

        //Example Method
        public String Locate()
        {
            return String.Format("Product {0}: {1} located", pId, pName);
        }

        //The price will be different when displayed to the consumer as this will have margin added, so let's delegate the price calculation to each implementation
        public abstract decimal DisplayPrice();

    }
}

The Interface 'IProduct'

namespace com.kewney.examples.abintex
{
    /// 
    /// Summary for IProduct
    /// 

    public interface IProduct
    {

        int ID
        {
            get { }
            set { }
        }

        String ProductName
        {
            get { }
            set { }
        }

        String ProductDescription
        {
            get { }
            set { }
        }

        decimal ProductBuyPrice
        {
            get { }
            set { }
        }

        String Locate();

        decimal DisplayPrice();
    }
}

Inherited Objects #1: Product_Staff

namespace com.kewney.examples.abintex
{

    /// 
    /// Summary for Product_Staff
    /// Note: In this example, the DisplayPrice is calculated using the abstract class
    /// 
    
    public class Product_Staff : Product // Inheriting from the abstract class Product
    {

        //It's inheriting from the abstract class therefore no properties or fields should be present here

        public Product_Staff() { }

        public override int ID
        {
            get
            {
                return pId;
            }
            set
            {
                pId = value;
            }
        }
        
        public override String ProductName
        {
            get
            {
                return pName;
            }
            set
            {
                pName = value;
            }
        }

        public override String ProductDescription
        {
            get

            {
                return pDescription;
            }
            set
            {
                pDescription = value;
            }
        }

        public override decimal ProductBuyPrice
        {
            get
            {
                return pCost;
            }
            set
            {
                pCost = value;
            }
        }

        //Locate method implemented in the abstract class
        public new String Locate()
        {
            return base.Locate();
        }
      
        //This abstract method that is different for staff than for customers so I'm overriding it here
        public override decimal DisplayPrice()
        {
            return String.Format("Product {0} price for staff is {1}, calculated via abstract class", base.pName, (base.pCost * 1));
        }
    }
}

Inherited Objects #2: Product_Customer

namespace com.kewney.examples.abintex
{
    /// 
    /// Summary for Product_Customer
    /// Note: In this example, the DisplayPrice is calculated using the abstract class
    /// 

    public class Product_Customer : IProduct // Inheriting from the interface IProduct
    {

        //Properties and fields defined here
        protected int pId;
        protected String pName;
        protected String pDescription;
        protected decimal pCost;

        public Product_Customer()
        {
            //
            // TODO: Add constructor here
            //
        }

        public int ID
        {
            get
            {
                return pId;
            }
            set
            {
                pId = value;
            }
        }

        public String ProductName
        {
            get
            {
                return pName;
            }
            set
            {
                pName = value;
            }
        }

        public String ProductDescription
        {
            get
            {
                return pDescription;
            }
            set
            {
                pDescription = value;
            }
        }

        public decimal ProductBuyPrice
        {
            get
            {
                return pCost;
            }
            set
            {
                pCost = value;
            }
        }

        //N.B Locate is completed within the object this time
        public String Locate()
        {
            return String.Format("Product {0} found", pName);
        }

        //This abstract method that is different for staff than for customers so I'm overriding it here
        public override decimal DisplayPrice()
        {
            return String.Format("Product {0} price for staff is {1}, calculated via interface", base.pName, (base.pCost * 2));
        }
    }
}

Example to test Interface and Abstract Class

namespace com.kewney.examples.abintex
{

    public class TestAbstractAndInterface
    {

        private void TestInterface() // As Customer
        {

            IProduct prod;

            Product_Customer prod = new Product_Customer();

            prod = emp1;
            prod.ID = 1;
            prod.ProductName = "simfree.net Account";
            prod.ProductDescription = "the easiest, most cost effective way to use text messaging in business";
            prod.ProductBuyPrice = 24.00;

            //call the DisplayPrice method
            MessageBox.Show(prod.DisplayPrice().ToString());

        }

        private void TestAbstract() // As Staff
        {

            Product prod;

            prod = new Product_Staff();
            
            prod.ID = 1;
            prod.ProductName = "simfree.net Account";
            prod.Product Description = "the easiest, most cost effective way to use text messaging in business";
            prod.ProductBuyPrice = 24.00;

            //call the DisplayPrice method
            MessageBox.Show(prod.DisplayPrice().ToString());

        }
    }
}

If you're looking for more information or are interested in a view from a developer taking a SOLID perspective, check out Pradeep's post here.

View Post (1383) or Add Comments (11)


Flattening nested object properties in Entity Framework & ASP.NET MVC

When using the Microsoft ASP.NET MVC framework, I always create a set of partial classes relating to my database objects to centralise validation and add additional properties. When using Telerik Grid control for MVC, however, you cannot bind, page or sort when there is a column which is bound to such a property because Entity Framework fails to translate those properties to SQL.

Occasionally, you just need to create a flattened representation of a set of objects and one solution is to use LINQ "projection" to output a flat view model object:

Here's the ActionResult which, using projection, flattens the UserModel enumerables into a flat UserViewModel:

 [GridAction]
        public ActionResult _UserGrid()
        {
            var model = from o in new UserRepository().GetUsers()
                        select new UserViewModel
                        {
                            Full_Name = o.Person.Person_nameFirst,
                            Created = o.Created,
                            Email = o.Person.First,
                            ID = o.ID,
                            Username = o.Username
                        };
            return View(new GridModel { Data = model });
        }

Here's the view model itself:

namespace Project.EF
{
    public class UserListViewModel
    {

        public int ID
        {
            get;
            set;
        }

        public string Full_Name
        {
            get;
            set;
        }

        public string Username
        {
            get;
            set;
        }
        public string Email
        {
            get;
            set;
        }
        public DateTime? Created
        {
            get;
            set;
        }
    }
}

And here's our original partial class

namespace Project.EF
{
    [Bind(Include = "myfields")]
    [MetadataType(typeof(User_Validation))]
    public partial class User
    {
        public string FullName
        {
            get { return string.Format("{0} {1}", Person.First, Person.Last); }
        }
        public bool IsValid
        {
            get { return (GetRuleViolations().Count() == 0); }
        }
        public bool IsValidRecord
        {
            get { return (ID > 0); }
        }

        public IEnumerable GetRuleViolations()
        {
            yield break;
        }
    }
    public class User_Validation
    {
        [HiddenInput(DisplayValue = false)]
        public int ID { get; set; }
    }
}

View Post (1653) or Add Comments (39)


String Extension Collection for C#

This article brings a small collection of my more commonly used string extensions. For those who don't know about extension methods, I suggest reading this short article.

Get the initials from a string

public static string ToInitials(this string str)
    {
      return Regex.Replace(str, @"^(?'b'\w)\w*,\s*(?'a'\w)\w*$|^(?'a'\w)\w*\s*(?'b'\w)\w*$", "${a}${b}", RegexOptions.Singleline)
    }

Remove line breaks from string

public static string RemoveLineBreaks(this string lines)
{
  return lines.Replace("\r", "").Replace("\n", "");
}

Replace line breaks in a string

public static string ReplaceLineBreaks(this string lines, string replacement)
{
    return lines.Replace("\r\n", replacement)
                    .Replace("\r", replacement)
                    .Replace("\n", replacement);
}

Strip HTML syntax from a string

public static string StripHtml(this string html)
{
   if (string.IsNullOrEmpty(html))
            return string.Empty;
   return Regex.Replace(html, @"<[^>]*>", string.Empty);
}

Pluralise a word

public static string Pluralise(this string value, int count) 
{ 
    if (count <= 1) 
    { 
        return value; 
    } 
    return PluralizationService 
        .CreateService(new CultureInfo("en-US")) 
        .Pluralize(value); 
}

and then

Console.WriteLine( 
    "You have {0} {1} left", player.Lives, "life".Pluralise(player.Lives) 
); 

Get Suffix From Date

    public static string GetDateSuffix(this DateTime date)
    {
        string day = date.Day.ToString();
        if (day.EndsWith("1"))
        {
            return day.StartsWith("1") && date.Day != 1 ? "th" : "st";
        }
        else if (day.EndsWith("2"))
        {
            return day.StartsWith("1") ? "th" : "nd";
        }
        else if (day.EndsWith("3"))
        {
            return day.StartsWith("1") ? "th" : "rd";
        }
        return "th";
    }

Add Working Days to Date

 public static DateTime AddWeekdays(DateTime start, int days)
        {
            int remainder = days % 5;
            int weekendDays = (days / 5) * 2;
            DateTime end = start.AddDays(remainder);

            if (start.DayOfWeek == DayOfWeek.Saturday && days > 0)
            {
                // fix for saturday.          
                end = end.AddDays(-1);
            } if (end.DayOfWeek == DayOfWeek.Saturday && days > 0)
            {
                // add two days for landing on saturday        
                end = end.AddDays(2);
            }
            else if (end.DayOfWeek < start.DayOfWeek)
            {
                // add two days for rounding the weekend      
                end = end.AddDays(2);
            }
            // add the remaining days   
            return end.AddDays(days + weekendDays - remainder);
        }

View Post (955) or Add Comments (1)


You can manage your Kewney.com account by logging in. [ Log On ]