Bit.ly API: Shorten URLs / Reverse Long URLs / Get QR Code Image

17. March 2011 16:03

.NET Framework API C# Utils 

If you have long URLs and other and want to create short URLs then Bit.ly API can help. I wrote a wrapper class which can let me create short URLs in jiffy. I was working on Bit.ly API to create my short URLs with a click of a button (that's for my personal use). Therefore, I ended up with a 'short' class to create shor URLs using Bit.ly API. What you need is a login and an apikey, which you can have one for yourself by signing up for a free account. You can find your apikey here after login. The class gives you two ways to make short URL, one with XML and the other with plain TEXT. I haven't write anything for JSON as it was not required at all to me in any ways. I am using plain TEXT for this example. You can read Bit.ly API official documentation for more information.

The below class can be used to create short URLs using Bit.ly API, reverse the short URLs and get the original URL. Also if you are not aware you can have a QR code of your short URL. Read more about QR Code here. If you are using Bit.ly or Goo.gl to shorten your URLs then you can have the QR code image by adding .qrcode in the end of the short URL (See in the code example below)

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

namespace Bitly.API
{

    public class BitlyData
    {
        #region Properties

        public static string APIKEY { get; set; }
        public static string LoginName { get; set; }

        public static string StatusCode { get; set; }
        public static string StatusDesc { get; set; }
        public static string ShortURL { get; set; }
        public static string LongURL { get; set; }
        public static string HashCode { get; set; }
        public static string GlobalCode { get; set; }
        public static string NewHash { get; set; }

        #endregion
    }

    public class Bitly
    {

        #region Bit.Ly Variables

        private static string URL = "http://api.bit.ly/v3/shorten?login=";

        private static string BitResponse = "";

        #endregion

        #region Enums

        public enum Format
        {
            XML,
            JSON,
            TXT
        }

        #endregion

        #region Sample Response
        //        <?xml version="1.0" encoding="utf-8"?>
        //<response>
        //    <status_code>200</status_code>
        //    <status_txt>OK</status_txt>
        //    <data>
        //        <url>http://bit.ly/ekYLee</url>
        //        <hash>ekYLee</hash>
        //        <global_hash>gBH72m</global_hash>
        //        <long_url>http://midnightprogrammer.net/post/Windows-7-Development-Working-With-Task-Dialog-Class.aspx</long_url>
        //        <new_hash>1</new_hash>
        //    </data>
        //</response>

        #endregion

        public static string ShortURL(string LongURL, Format ReqFormat = Format.TXT)
        {
            string sURL = string.Empty;
            string BitLyURL = URL + BitlyData.LoginName + "&apikey=" + BitlyData.APIKEY + "&longUrl=" + LongURL + "&format=";

            if (ReqFormat == Format.JSON)
            {
                throw new NotImplementedException("This method is not implemented yet!");
            }

            if (ReqFormat == Format.XML)
            {
                BitResponse = new WebClient().DownloadString(BitLyURL + "xml");
                string Response = BitResponse;

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(Response);
                XmlNodeList XlistResponse = doc.GetElementsByTagName("response");

                foreach (XmlNode XResnode in XlistResponse)
                {
                    XmlElement ResElm = (XmlElement)XResnode;

                    BitlyData.StatusCode = ResElm.GetElementsByTagName("status_code")[0].InnerText;

                    if (BitlyData.StatusCode != "200")
                    {
                        BitlyData.StatusDesc = ResElm.GetElementsByTagName("status_txt")[0].InnerText;
                        return BitlyData.StatusDesc;
                    }
                }

                if (BitlyData.StatusCode == "200")
                {

                    XmlNodeList XlistData = doc.GetElementsByTagName("data");

                    foreach (XmlNode XDatanode in XlistData)
                    {
                        XmlElement DataElm = (XmlElement)XDatanode;

                        BitlyData.ShortURL = DataElm.GetElementsByTagName("url")[0].InnerText;
                        BitlyData.LongURL = DataElm.GetElementsByTagName("long_url")[0].InnerText;
                        BitlyData.HashCode = DataElm.GetElementsByTagName("hash")[0].InnerText;
                        BitlyData.GlobalCode = DataElm.GetElementsByTagName("global_hash")[0].InnerText;
                        BitlyData.NewHash = DataElm.GetElementsByTagName("new_hash")[0].InnerText;
                    }
                }
            }

            if (ReqFormat == Format.TXT)
            {
                if (ReqFormat == Format.TXT)
                {
                    BitResponse = new WebClient().DownloadString(BitLyURL + "txt");
                    string Response = BitResponse;

                    BitlyData.ShortURL = Response;
                }
            }

            return sURL = BitlyData.ShortURL;
        }

        public static string ReverseShortURL(string ShortURL)
        {
            HttpWebRequest Webrequest = (HttpWebRequest)HttpWebRequest.Create(ShortURL);
            HttpWebResponse Webresponse = (HttpWebResponse)Webrequest.GetResponse();
            Uri uri = Webresponse.ResponseUri;
            return uri.AbsoluteUri;
        }

        public static string GetQRCodeURL(string ShortURL)
        {
            string QRCodeURL = string.Empty;
            QRCodeURL = ShortURL + ".qrcode";
            return QRCodeURL;
        }
    }
}

In the above class you can see that the second parameter is accepting TXT by default. So, if you call the method with or without the second parameter it will still work with the default parameter TXT. The enumeration called Format contains all the possible format of all the formats which is accepted by Bit.ly API. The second parameter in the class above should be removed if you plan to use the above code with the lower versions of .NET i.e. 3.x / 2.0

Sample Usage .NET 3.x / 2.0

Bitly.API.BitlyData.LoginName = "LOGIN NAME GOES HERE";
Bitly.API.BitlyData.APIKEY = "API KEY GOES HERE";
Console.WriteLine("Short URL: "+Bitly.API.Bitly.ShortURL("http://midnightprogrammer.net/post/9-Promises-Should-Be-Taken-Before-Choosing-IT-Profession.aspx", Bitly.API.Bitly.Format.TXT));
Console.WriteLine("Reverse URL: "+Bitly.API.Bitly.ReverseShortURL("http://bit.ly/eZ1kdb"));
Console.WriteLine("QRCode Image URL " + Bitly.API.Bitly.GetQRCodeURL("http://bit.ly/eZ1kdb"));

Sample usage .NET 4.0

Bitly.API.BitlyData.LoginName = "LOGIN NAME GOES HERE";
Bitly.API.BitlyData.APIKEY = "API KEY GOES HERE";
Console.WriteLine("Short URL: "+Bitly.API.Bitly.ShortURL("http://midnightprogrammer.net/post/9-Promises-Should-Be-Taken-Before-Choosing-IT-Profession.aspx", Bitly.API.Bitly.Format.TXT));
Console.WriteLine("Reverse URL: "+Bitly.API.Bitly.ReverseShortURL("http://bit.ly/eZ1kdb"));
Console.WriteLine("QRCode Image URL " + Bitly.API.Bitly.GetQRCodeURL("http://bit.ly/eZ1kdb"));

I have tested my code with Console Application, but you can test it with web or Windows form application. Note that the default parameters are only accepted if you are working with .NET 4.0 and not by the lower versions of .NET. If you wish to use the second parameter in .NET 4 then also it will work, but not using it with lower version will give you error.

I hope this class helps someone around the globe!

Currently rated 4.7 by 6 people

Code Snippet: Export DataGridView To Excel With Columns

25. January 2011 16:12

C# Code Snippets 

This is among one of the best code snippet I have and using since long to export the datagridview to excel. The best part of this code snippet is that it just don't uses the excel interop, so you need not to worry about the Office version or PIAs installed at user's machine. What actualy is needed is just a Reflection namespace - System.Reflection and it will bind the data to the instance of the excel application.

 

private void Export2Excel(DataGridView datagridview, bool captions)
{
    if (datagridview.ColumnCount > 0)
    {
        string[] strArray = new string[datagridview.ColumnCount];
        string[] strArray2 = new string[datagridview.ColumnCount];
        int num = 0;
        int index = 0;
        int num3 = 0;
        for (index = 0; index < datagridview.ColumnCount; index++)
        {
            strArray[index] = datagridview.Rows[0].Cells[index].OwningColumn.Name.ToString();
            if ((num > 0) && ((index % num) == 0))
            {
                num = 0;
            }
            num3 = index / 0x1a;
            if (num3 == 0)
            {
                num = index + 0x41;
                strArray2[index] = Convert.ToString((char)num);
            }
            else
            {
                int num4 = num3 + 0x40;
                num = (index % 0x1a) + 0x41;
                strArray2[index] = Convert.ToString((char)num4) + Convert.ToString((char)num);
            }
        }
        try
        {
            object obj7;
            object target = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
            object obj4 = target.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, target, null);
            object obj3 = obj4.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, obj4, null);
            object obj5 = obj3.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty, null, obj3, null);
            object[] args = new object[] { 1 };
            object obj6 = obj5.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, obj5, args);
            if (captions)
            {
                index = 0;
                while (index < datagridview.ColumnCount)
                {
                    args = new object[] { strArray2[index] + "1", Missing.Value };
                    obj7 = obj6.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, obj6, args);
                    args = new object[] { strArray[index] };
                    obj7.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, obj7, args);
                    index++;
                }
            }
            for (num = 0; num < datagridview.RowCount; num++)
            {
                for (index = 0; index < datagridview.ColumnCount; index++)
                {
                    args = new object[] { strArray2[index] + Convert.ToString((int)(num + 2)), Missing.Value };
                    obj7 = obj6.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, obj6, args);
                    args = new object[] { datagridview.Rows[num].Cells[strArray[index]].Value.ToString() };
                    obj7.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, obj7, args);
                }
            }
            args = new object[] { true };
            target.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, target, args);
            target.GetType().InvokeMember("UserControl", BindingFlags.SetProperty, null, target, args);
        }
        catch (Exception exception)
        {
            MessageBox.Show(("Error: " + exception.Message) + " Line: " + exception.Source, "Error");
        }
      }
    }
Currently rated 5.0 by 2 people

Windows 7 Development: Working With Task Dialog Class

24. January 2011 16:57

API C# Windows 

Last year, I blogged about few things related to Windows 7 development which includes Jump Lists and Glass Form. The Windows 7 API Code Pack comes with many other features which can be used while developing applications for Windows 7 platform. The Windows 7 API Code Pack comes with some sample applications which exposes the power of the API.

In one of my previous projects I used the Task Dialog class to use some cool looking message boxes like the one we see in Windows 7. If you see the sample code and and the executable, they are working fine but when you write the same code in the code in your application, this will not turn out to be as you would have expected. You will see a runtime error as the one below.

 

This problem can be resolved by adding a app.manifest file to your project and modifying some part of it. Move to the end of the file and un-comment the <dependency> section of the file.

<dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
</dependency>

Hit F5 again and this will do the trick for you, this time you will be able to view the message box as you wanted to. The API sample contains code for all the possible / available task dialog for you to use. But the usage is bit difficult as this cannot be acaieved in a single line like we do with the MessageBox class. Therefore I suggest you to build a helper class / function to get this easy for you. As I used this in one of my projects I have two functions one for showing the information and error messages respectively. You can also have a overload method for this, but as I have used different method names instead as I will be using only two dialogs throughout my project.

For Error Messages:

public static void ShowErrorMessage(string ErrorTitle, string Instruction, string ErrorMessage, string ErrorTrace)
{
            TaskDialog tdError;
            tdError = new TaskDialog();
            tdError.DetailsExpanded = false;
            tdError.Cancelable = true;
            tdError.Icon = TaskDialogStandardIcon.Error;

            tdError.Caption = ErrorTitle;
            tdError.InstructionText = Instruction;
            tdError.Text = ErrorMessage;
            tdError.DetailsExpandedLabel = "Hide details";
            tdError.DetailsCollapsedLabel = "Show details";
            tdError.DetailsExpandedText = ErrorTrace;

            tdError.Show();
}

All the properties in the above function is self-explainatory. The code at line:12 will have a expander in the dialog box which will contain more details of the exception.

Function for showing information is also the same but with few things "missing":

public static void ShowInfoMessage(string InfoTitle, string Information, string Message)
{
            TaskDialog tdInfo;
            tdInfo = new TaskDialog();
            tdInfo.DetailsExpanded = false;
            tdInfo.Cancelable = true;
            tdInfo.Icon = TaskDialogStandardIcon.Information;

            tdInfo.Caption = InfoTitle;
            tdInfo.InstructionText = Information;
            tdInfo.Text = Message;
            tdInfo.Show();
}

Sample Usage

//For Error Dialog
ShowErrorMessage("Application Error", "There was an error in creating XML file", ex.Message, ex.StackTrace);

//For Information Dialog
ShowInfoMessage("Application Name", "Image more than 32x32 pixels will be rejected", "Please check the image pixel before you use choose a package icon");

 Error Dialog Box

 Click the Show Details expander icon to view the complete error stack trace.

 Information Dialog Box  

This is just the two types of dialogs I have used for my project, but there are more supported in the API. So to get started see the sample project accompanying the API Code Pack including the one you see while running programs as Administrator while UAC is turned on, a dialog box with a progress bar and lots of more to check. The samples above would get you started.

 If you are a Visual Studio 2010 user with NuGet installed, then you can add the API reference to your project with the below command.
Install-Package Windows7APICodePack
 No Rating

Autocomplete With jQuery and ASP.NET

19. December 2010 01:46

ASP.NET C# Jquery 

Building auto-complete feature with jQuery is easy and you can build this in no time. It's your wish if you want to use ADO.NET or EF (LINQ) to get this done, it works great for all. The sample application I build is using both ADO.NET and EF. So let's begin up getting files under one hood.

Use the below live links for jQuery auto-complete and CSS.

<link rel="stylesheet" href="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.js"></script>

You can also download these files and use them in your project, if you are planning to run your application offline. For this demonstration, I have downloaded the files. I am using both ADO.NET and LINQ to auto-complete with jQuery auto-complete pug-in.

Starting up with ADO.NET, as we were/are using this for so many years now and therefore there should be no problem for anyone using it. Simple page behind code to get the full list of countries in the world (I hope I have all of them) and seperate each country name with a '|' pipe symbol so I can split countries name and set it to the text box for auto-complete.

 public partial class _Default : System.Web.UI.Page
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["constr"].ConnectionString);
        SqlCommand cmd;
        SqlDataReader dr;

        public string Listcountries;

        private string countryName()
        {

            StringBuilder sb = new StringBuilder();
            cmd = new SqlCommand("Select country_name from Country order by country_name", con);
            con.Open();
            dr = cmd.ExecuteReader();

            while (dr.Read())
            {
                sb.Append(Convert.ToString(dr[0] + "|"));
            }

            return Convert.ToString(sb);
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            Listcountries = countryName();
        }
    }

Done with code behind and now only requires few lines of client script on the page to get the auto-complete running.

<script type="text/javascript">
        $(document).ready(function () {
            var cc = '<%=Listcountries%>'.split("|");
            $("#autoText").autocomplete(cc);
        });
</script>

The same can be done with LINQ but the jQuery script part will be the same.

public partial class AutocompleteLINQ : System.Web.UI.Page
    {
        DeveloperDBEntities db = new DeveloperDBEntities();
        public IQueryable countries;
        public string Listcountries;

        protected void Page_Load(object sender, EventArgs e)
        {
            countries = from c in db.Countries select c;
            foreach (Country cobj in countries)
            {
                Listcountries += cobj.Country_Name + "|";
            }
        }
    }

Just for your ease to use this project as it is, I have included the SQL scripts for the country table. Hope this helps you in building another great or a part of your application.

Downalod: JqueryAutoComplete.zip (210.73 kb)

Currently rated 3.3 by 6 people

Disable "X" Close Button On Your Windows Form Application

12. December 2010 07:55

C# Code Snippets 

Recently, someone on MSDN forums asked this question on how to disable the "X" a.k.a. close button in his windows form application so the user is forced to close the application from the cancel button on the form and not from the close button. He wanted this for his application which requires registration first before a user can start using his application.

I don't know the answer so I bing arond a bit and find a solution posted by someone though I don't have the name but it worked like a charm....!!

We need some interoperability to do this, therefore get the namespace System.Runtime.InteropServices
Code:

private const int MF_BYPOSITION = 0x400;
[DllImport("User32")]
private static extern int RemoveMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("User32")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("User32")]
private static extern int GetMenuItemCount(IntPtr hWnd);

Below code goes to the load event of your form:

IntPtr hMenu = GetSystemMenu(this.Handle, false);
int menuItemCount = GetMenuItemCount(hMenu);
RemoveMenu(hMenu, menuItemCount - 1, MF_BYPOSITION);

Time to press 'F5'....and the close button is now disabled on the form.

Download: CloseButton.zip (43.08 kb)

 No Rating