C# – Limit Paragraph Length using Simple Extension Method

Happy New Year 2016 !

In most of the web applications, you will encounter a scenario where you have to display the summary of the page in limited amount of space. For example, on a section level page, sometimes you are required to display sub section summary information but due to design constraints, you can only display 80 characters.

The .NET framework provides .Substring() method to limit the string length and generate a new sub-string but this method is not clever enough to distinguish between words and empty spaces in a long paragraph and can result in a sub-string where a word has been truncated in the middle of being displayed, giving bad output to the end user.  How can we solve this ?

Here is a simple string extension method that will nicely truncate the paragraph and it will also add “…” at the end of the returned string value.

Step 1 : Add this extension method class in your project

namespace StringExtensions.LimitSentenceLength
{
    public static class StringExtensions
    {
        public static string LimitSentenceLength(this string paragraph, int maximumLenght)
        {
            //null check
            if (paragraph == null) return null;

            //less than maximum length, return as it is
            if (paragraph.Length <= maximumLenght) return paragraph; 
            //split the paragraph into indvidual words 
            string[] words = paragraph.Split(' '); 
            //initialize return variable 
            string paragraphToReturn = string.Empty; 
            //construct the return word 
            foreach (string word in words) 
           { 
            //check if adding 3 to current length and next word is more than maximum length. 
            if ((paragraphToReturn.Length + word.Length + 3) > maximumLenght)
            {
              //append "..."
              paragraphToReturn = paragraphToReturn.Trim() + "...";
              //exit foreach loop
              break;
             }
             //add next word and continue
             paragraphToReturn += word + " ";
            }
           return paragraphToReturn;
        }
    }
}

Step 2 : From your main application, you can call this method as following :

using System;

namespace StringExtensions.LimitSentenceLength
{
    class Program
    {
        private static string Paragraph => "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

        static void Main(string[] args)
        {
            Console.WriteLine(Paragraph.LimitSentenceLength(50));
            //Lorem ipsum dolor sit amet, consectetur...
            Console.WriteLine(Paragraph.LimitSentenceLength(100));
            //Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut...
            Console.WriteLine(Paragraph.LimitSentenceLength(150));
            //Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam,...
            Console.WriteLine(Paragraph.LimitSentenceLength(200));
            //Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut...
        }
   
    }
}

How simple is that !!!

Sample code is available on GitHub

Advertisements

C# – Random ordering of IEnumerable using Extensions

This is just a quick post about random ordering of IEnumerable types using C# extension. For example you have a IEnumerable of type ‘Employee’ object and you want to randomly pick 7 employee objects, how would you do that? This blog post will create a simple extension method for IEnumerable and show how to use it.

Step 1 : Create an extension class for IEnumerable as below :

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

namespace Sample
{
    public static class EnumerableExtentions
    {
       public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
        {
            var range= new Random();
            return source.Randomize(range);
        }

        private static IEnumerable<T> Randomize<T>(this IEnumerable<T> source, Random range)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (range== null) throw new ArgumentNullException("range");

            return source.RandomizeAlgorithm(range);
        }

        private static IEnumerable<T> RandomizeAlgorithm<T>(this IEnumerable<T> source, Random range)
        {
            var temp = source.ToList();

            for (int i = 0; i < temp.Count; i++)
            {
                int j = range.Next(i, temp.Count);
                yield return temp[j];

                temp[j] = temp[i];
            }
        }
    }
}

Step 2 : Use it within your main code as below :

           //get all employees
            var employees = Employee.GetAllEmployee();
            //print in sequence
            PrintEmployees(employees);
            //randomize using extension
            var randomEmployees = Employee.GetAllEmployee().Randomize();
            //print them again
            Console.WriteLine("**************");
            PrintEmployees(randomEmployees);

Job Done!

Sample code is available on GitHub

Note : I am using Fisher–Yates shuffle  algorithm for randomizing the collection.

Getting started with MongoDB 3.0 using some new features of C# 6.0

Recently, I had to work on an application which used MongoDB as a back-end database. As it was my first MongoDB based project using C#, I went through a learning curve and thought it will be a good idea to do a step-by-step guide. So, if you are new to MongoDB, here is a quick post to get you up and running

Step 1: Download and install VS 2015 Community edition, it’s free for personal use with registered email address!

VS2015_Install

Step 2: Download MongoDB and install it on your local machine.

MongoDB_Install

Step 2.1 Create a data directory or empty folder at C:\data\db (this is the default location for MongoDB to store files, but can be changed)

Step 2.2 Open CMD with administrative privileges and navigate to MongoDB install folder and start mongod.exe program. In my case the path was C:\program files\mongodb\server\3.0\bin and then the command mongod.exe

MongoDB_Starting

Step 3: Download RoboMongo which is an open-source GUI for MongoDB management.

RoboMongo_Install

Step 3.1 Assuming MongoDB is up and running, create a new “localhost” connection and test it.

Step 3.2 Click on View > Explorer and you will see list of localhost DBs.

RoboMongo_Connection

Step 4: Open VS 2015 and create a new Console Application (for production purposes, you might need a class library, but for demo I am using console application)

MongoDBTestApp

Step 5: Right click on References > NuGet Packages and install ‘Official .NET Driver for MongoDB’

MongoDB.Driver.NuGet

Step 6: Create your collection class, for purpose of this blog, I have created a Customer class.

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System;

namespace MongoDBTestApp
{
    public class Customer
    {
        //required field to perform read/write opertions on Bson or Binary Json
        [BsonElement("Id")]
        public ObjectId Id { get; set; }

        //C# 6.0 property initializers
        public string FirstName { get; set; } = "John";
        public string LastName { get; set; } = "Doe";
        public DateTime Timestamp  { get; set; } = DateTime.UtcNow;
    }
}

Step 7:  Insert objects as collection in Mongo DB

using MongoDB.Driver;
using System.Threading.Tasks;

namespace MongoDBTestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //creates a MongoDB client from conn string
            var client = new MongoClient("mongodb://localhost");
            //gets the database within client, if it doesn't exists, creates it
            var database = client.GetDatabase("customer");
            //gets the collection from the database,if it doesn't exists, creates it
            var collection = database.GetCollection("customers");
            //insert into database
            Task.WaitAll(InsertCustomer(collection));
            
        }

        static async Task InsertCustomer(IMongoCollection collection)
        {
            await collection.InsertOneAsync(new Customer());
        }
        
    }
}

MongoDB_InsertCustomer

Step 8: Find your object from Mongo DB and display it

 static async Task FindCustomer(IMongoCollection collection)
        {
            //creates a filter to find Bson Document
            var filter = Builders.Filter.Eq(c => c.FirstName, "John");
            //runs the query to find it
            var query = await collection.Find(filter).ToListAsync();
            //gets the customer
            var customer = query.FirstOrDefault();
            //displays the customer using new C#6 string formatters
            Console.WriteLine($"Customer {customer.FirstName} {customer.LastName} is found!");

        }

MongoDB_FindCustomer

What you have now is a fully functional MongoDB application where you can store records and retrieve records, how easy was that!

All code is available from GitHub.

Thanks

Naveed.

C# Enums – Handling Long Descriptive String Values – Using Reflection

Consider the following scenario, you have an Enum, for which you have ‘Description’ attributes as shown below

public enum Status
 {
 [Description("Status is Incomplete")]
 Incomplete = 0,
 [Description("Status is Complete")]
 Complete = 1,
 [Description("Status is Reserved")]
 Reserved = 2,
 [Description("Stauts is Confirmed")]
 Confirmed = 3,
 [Description("Stauts is Cancelled")]
 Cancelled = 99
 }

You want to display these values in a drop down, where the text field is same as the Enum’s ‘Description’ text and the drop down value field same as the Enum’s int value.

If you have one Enum with such requirements, you would probably hard code it (I know), but in real world applications, you would have nearly 30 to 40 Enums, used at more than one place in the application, hence hard coding to the drop down is not an option. Also, let suppose we have the project requirement that the drop down should update itself when Enum is updated.

In short, we want a dynamic drop down, whose source is Enum values and if we add/remove values to the Enum, the drop down will update it self.

How to go about this ?

Lets use .NET extension and reflection and try to achieve this

The following code will use return the ‘Description Attribute’ of any Type of source using reflection

public static string GetDescriptionAttr(this T source)
 {
 FieldInfo fi = source.GetType().GetField(source.ToString());

 if (fi == null)
 return string.Empty;

 var attribute = (DescriptionAttribute) fi.GetCustomAttributes(typeof (DescriptionAttribute), false)[0];

 if (attribute == null)
 return string.Empty;

 return attribute.Description;
 }

Once this code is in place, we could write a helper function which will convert Enums to ListItemCollection where ‘Description’ attribute is used as text and Enum’s int value is used as ‘value’ field for the drop down option.

 public static ListItemCollection EnumToList(Type enumType)
 {
 var list = new ListItemCollection();

 foreach (var type in Enum.GetValues(enumType))
 {
   list.Add(new ListItem(String.Format(" {0}", type.GetDescriptionAttr()), ((int)type).ToString()));
 }

 return list;
 } 

And finally, in the code behind, you just need to pass in the Enum value to this helper method, which will use reflection and return the dynamic list for the drop down

MyDropDown.DataSource = EnumToList(typeof(Status));
MyDropDown.DataBind();

Thanks !

Sitecore : Adding a Twitter Pod using LINQ To Twitter

In almost all the projects I have done in past year or so, a common requirement among the clients have been that they want the ability to add Twitter Pods on pages and also have the ability to change the account name based upon their campaign or department.

For the purpose of the post, I will be using Sitecore CMS and LINQ To Twitter library to show how simple it is to create a Twitter Pod/module.

Let suppose we only want to display top  tweet from an account/twitter handle, which is define in the Sitecore CMS

Steps:

1. Create a data template property in the CMS as ‘Twitter Account Name’ or whatever you like

2. Create a standard .NET User Control and lets call it ‘TwitterPod.ascx’

3. Reference LINQ to Twitter library in your project (download it from here http://linqtotwitter.codeplex.com/ and also read its documentation)

4. As per Twitter API 2.0 you need to get Consumer Key, Consumer Secret, Access Token, Access Token Secret values from http://dev.twitter.com for any applications that you are creating. Log-in there and follow the steps to get these values.

5. Add these Twitter API 2.0  values to web.config

6. Let suppose this is your .ascx control markup

<div><asp:HyperLink ID="HyperLinkFollowAccount" runat="server" Target="_blank"></asp:HyperLink></div>

<div class="twitter">
<asp:HyperLink ID="HyperLinkFirstTweet" runat="server">
<p><asp:Literal ID="LiteralFirstTweet" runat="server"></asp:Literal>
<p>Posted <asp:Literal ID="LiteralFirstPostedTime" runat="server"></asp:Literal></p>
</asp:HyperLink>
</div>

7. Add these ‘static strings’ to your User Control class

private static string ConsumerSecret

{

get { return WebConfigurationManager.AppSettings["ConsumerSecret"]; }

}

private static string ConsumerKey

{

get { return WebConfigurationManager.AppSettings["ConsumerKey"]; }

}

private static string AccessToken

{

get { return WebConfigurationManager.AppSettings["AccessToken"]; }

}

private static string AccessTokenSecret

{

get { return WebConfigurationManager.AppSettings["AccessTokenSecret"]; }

}

8.  Twitter API 2.0 requires OAuth Authentication, to get that add this to Page_Load of your User Control

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
var auth = new SingleUserAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = ConsumerKey,
ConsumerSecret = ConsumerSecret,
OAuthToken = AccessToken,
AccessToken = AccessTokenSecret
}
};

using (var twitterCtx = new TwitterContext(auth))
{
LoadTwitterFeeds(twitterCtx);
}
}
catch(Exception ex)
{
Sitecore.Diagnostics.Log.Error(ex.Message, this);
}
}
}

9.  LoadTwitterFeeds(twitterCtx) is your custom function where you can add your logic of getting tweets via Twitter API 2.0 and displaying them

10.

private void LoadTwitterFeeds(TwitterContext service)
{
try
{

string accountName = Sitecore.Context.Item["Twitter Account Name"] as string;

var tweets = (from tweet in service.Status

where tweet.ScreenName == accountName &&
tweet.Count == 1 &&
tweet.ExcludeReplies == true &&
tweet.IncludeRetweets == true &&
tweet.Type == StatusType.User
select tweet).FirstOrDefault();

if (tweets != null)
{

HyperLinkFollowAccount.NavigateUrl = "http://twitter.com/" + accountName.Replace("@", "");
HyperLinkFollowAccount.Text = "Follow " + accountName + " on Twitter";

LiteralFirstTweet.Text = tweets.Text;
LiteralFirstPostedTime.Text = tweets.CreatedAt.ToString();
HyperLinkFirstTweet.NavigateUrl = "https://twitter.com/" + tweets.User.Identifier.ScreenName + "/status/" + tweets.StatusID.ToString();}

catch (Exception ex)
{
Sitecore.Diagnostics.Log.Error(ex.Message, this);
}
}

11. Create a Sublayout for this User Control and add it to the Sitecore Layouts.

Note: You can also pass in the ‘Twitter Account Name’ as a parameter of the SubLayout
Note++: Umbraco and Episerver CMS can also use the same code with different CMS based API.

Thanks

Sitecore : Getting image field in code behind

This is just a quick post to show how to get image URL via code behind.

This is mostly useful when you are binding children items to a repeater or returning image URL in a JSON webservice

public static string GetImageURL(Item currentItem)
{
          string imageURL = string.Empty;
          Sitecore.Data.Fields.ImageField imageField = currentItem.Fields["Image"];
          if (imageField != null && imageField.MediaItem != null)
          {
            Sitecore.Data.Items.MediaItem image = new Sitecore.Data.Items.MediaItem(imageField.MediaItem);
            imageURL = Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(image));
          }
return imageURL;
}

Cheers

Sitecore vs Umbraco – A developer’s view

One Friday afternoon, I was sitting at my desk and fixing bugs (as usual), a member of sales team came up to me and said

“Hey Naveed, we have this interesting new client and they are not sure about which CMS to go for, they have finalised Sitecore and Umbraco as the last two, can you help”

I replied: “Sure, why not, what are their business requirements ?”

Sales person: “They are medium to large size organisation and have usual requirements like news, events, forums, blogs, video content etc, they want a simple to use CMS with multiple authors and security levels”
I replied: “Ok, Sitecore and Umbraco are both equally powerful in content generation and management, they both are based on .NET stack (.NET,C#,SQL) and both are highly customisable, so far they both can be their potential CMS, do you have more specific requirements ?”

Sales person: “Yes, in future, they would like to integrate with Sharepoint and their back-end CRM system”

I replied :”Sitecore comes with a sharepoint connector out-of-box whereas for Umbraco we have to custom build one. As long as their back end CRM exposes API, we can integrate any of the CMS system with their back end, this will be custom build in both cases, do you have any other requirements ?”

Sales person: “It is not a requirement but in their wish list to have personalised content for different regions or profile history”

I replied: “Sitecore comes with Customer Engagement Platform (CEP) and Online Marketing Suite (OMS) which can make their life easy in future, however, Umbraco lacks these customised modules. So it looks like Sitecore can be their potential candidate for CMS, also do you have any idea about their budget for the website?”

Sales person: “Yes, it’s a five figure sum, not sure what exactly their budget is”

I replied: “If they are tight on budget and can compromise on add-ons then Umbraco would be good to start off with but will have high maintenance cost if they go down the route implementing customised modules. However, paying for Sitecore licenses up front will give them added benefit to use some of the modules out of the box and will have low maintenance cost, I guess best would be to give them a demo of both CMS systems to the client and let them make informed decision”

Sales person: “Sounds like a plan, ok I will let them know, cheers”

Conclusion:

No CMS is right or wrong for your business out of the box, you have evaluate them against your own business requirements for the website. Open source may be cheaper to start off with but will have maintenance costs down the line.

Disclaimer: I have worked with both CMS systems and hold them up in same respect for what they do, I am not a sales person or work for either of the CMS systems, this is just my opinion as a third party developer