Consuming URL Shortening Services – 1click.at

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Read more about URL Shortening Services here.

Source- Elsheimy.Samples.ShortenSvcs.zip

Contents

Contents of this article:

  • Contents
  • Overview
  • Introduction
  • API
  • What’s next

Overview

Another article of our endless series that talks about accessing URL shortening services programmatically.

This article is talking about 1click.at shortening service, how you can use it, and how to access it via your C#/VB.NET application.

Introduction

We can’t say that 1click.at is not one of the well-known services nor it has anything special, however, as long as it provides an API we are very interested in it.

When you visit service website, http://1click.at, you can see that nothing easier from 1click.at, just push your long URL into the text box and click the shortening button.

API

1click.at provides you a very simple easy-to-use API. This API contains only one function that’s used for shortening URLs. Another good thing is that this function doesn’t require any kind of authentication for users. Therefore, you need just to send it your long URL (as you did with the website.)

The shortening function function is called http://1click.at/api.php, it accepts 3 arguments:

  1. action:
    Yet, it can accept only one value, shorturl, which orders the function to shorten the specified url.
  2. url:
    The long URL to be shortened.
  3. format:
    The format of the returned data from the function. Can be simple, xml, or json.

As you know, the .NET BCL doesn’t support JSON (some third-party components do,) and thus, we won’t cover JSON data returned from the function. Rather, we’ll concentrate on plain and XML data returned.

When the format of this function is XML, the returned data, if the function succeeded, is like the following if this is your first time you shorten this URL:

<result>
    <url>
        <keyword>GFbA1zL</keyword>
        <url>http://WithDotNet.net</url>
        <date>2010-12-17 20:14:04</date>
        <ip>0.0.0.0</ip>
    </url>
    <status>success</status>
    <message>http://WithDotNet.net added to database</message>
    <shorturl>http://1click.at/GFbA1zL</shorturl>
    <statusCode>200</statusCode>
</result>

If, however, this isn’t your first time you shorten this URL, you would get data like this:

<result>
    <status>fail</status>
    <code>error:url</code>
    <message>http://WithDotNet.net already exists in database</message>
    <shorturl>http://1click.at/GFbA1zL</shorturl>
    <statusCode>200</statusCode>
</result>

Anyway, you can retrieve the value of shorturl and forget about the rest.

Now, let’s try this function. We’ll try to shorten the URL http://WithDotNet.net with our function. First, connect the arguments, e.g. http://1click.at/api.php?action=shorturl&url=http://WithDotNet.net&format=xml. Now copy this address and paste it into your favorite browser. If everything was OK, you should see the short URL after clicking ‘Go’ in the browser toolbar.

Now, let’s do it in C# and VB.NET. Check the following function that tries to shorten long URLs via the id.gd API:

// C#

string Shorten(string url, bool xml)
{
    url = Uri.EscapeUriString(url);
    string reqUri =
String.Format("http://1click.at/api.php?action=shorturl&url={0}&format={1}",
        url, xml ? "xml" : "simple");

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
    req.Timeout = 10000; // 10 seconds

    // if the function fails and format==txt throws an exception
    Stream stm = req.GetResponse().GetResponseStream();

    if (xml)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(stm);

        // error checking for xml
        if (doc["result"]["statusCode"].InnerText != "200")
            throw new WebException(doc["result"]["statusCode"].InnerText);

        return doc["result"]["shorturl"].InnerText;
    }
    else // Text
        using (StreamReader reader = new StreamReader(stm))
            return reader.ReadLine();
}
' VB.NET

Private Function Shorten(url As String, xml As Boolean) As String
	url = Uri.EscapeUriString(url)
	Dim reqUri As String = "http://1click.at/api.php?action=shorturl&url={0}&format={1}"
	If (xml) Then
		reqUri = String.Format(reqUri, url, "xml")
	Else
		reqUri = String.Format(reqUri, url, "simple")
	End If

	Dim req As HttpWebRequest = DirectCast(WebRequest.Create(reqUri), HttpWebRequest)
	req.Timeout = 5000
	Dim stm As Stream = req.GetResponse().GetResponseStream()

	If xml Then
		Dim doc As New XmlDocument()
		doc.Load(stm)

		' error checking for xml
		If doc("result")("statusCode").InnerText <> "200" Then
			Throw New WebException(doc("result")("statusCode").InnerText)
		End If

		Return doc("result")("shorturl").InnerText
	Else
		' Simple
		Using reader As New StreamReader(stm)
			Return reader.ReadLine()
		End Using
	End If
End Function

Notice that we have used the function System.Net.Uri.EscapeUriString() to eliminate unacceptable characters from the URL by encoding them.

Notice too that we have included our code in a Try-Catch block so we can catch exceptions before they blow up our application.

What’s next

Consider reading other articles in this series here.

Consuming URL Shortening Services – X.co

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Read more about URL shortening services here.

Source- Elsheimy.Samples.ShortenSvcs.zip

Contents

Contents of this article:

  • Contents
  • Overview
  • Introduction
  • API
  • WCF Services
    • Squeeze Service
    • Reporting Service
  • RESTful Services
    • Squeeze Service
    • Reporting Service
  • Source Code
  • What’s next

Overview

This is another article of our URL shortening services series. This article is talking about X.co shortening service provided by Go Daddy. If you don’t know how to access this service from your .NET application, then it’s the time to.

We’ll have a complete discussion of the WCF services offered by X.co. Then, we’ll consider the RESTful interfaces provided.

Introduction

Today we are going to talk about one of the most popular URL shortening services on the web now; it’s the new X.co provided by Go Daddy, the dominating domain names and web hosting service provider.

While X.co is considered very new since it has released just few months ago, it gained support from users worldwide very quickly, and now it’s one of the most popular shortening services exist in the web. Although the interface provided to users doesn’t offer great functionality, the API interface it provides really deserves respect since it’s one of the most easiest yet powerful APIs (for shortening services) exist on the web now.

API

The most noticeable thing about X.co API is that unlike other APIs it’s based on ASP.NET and WCF (WOW!) Moreover, the WCF service provides you a RESTful interface. Thus, you end up with two interfaces, one is based on WCF, and other is a REST web service.

You might not be familiar with WCF or other new technologies related to versions higher than .NET 2.0, don’t worry it’s just a matter of names! You use WCF services the same way as with ordinary Web Services.

In this writing, we’ll first talk about WCF/Web service interfaces provided to you by X.co. After that, we’ll have a look at how RESTful interfaces fit in the picture.

Before we begin our discussion, you’ll need to grab your API key that’s required by all functions for authentication. To get your API key, first create a free account at http://www.godaddy.com if you don’t have one yet. Figure 1 shows the registration page.

Figure 1 - Go Daddy Registration Page

After you complete the registration process, go to http://x.co, login with your username and password, and go to Settings to get your API key. See figure 2.

Figure 2 - X.co API Key

Notice that this is a secret key and you should keep it away from intruder eyes. This key will be used in all of your work with X.co API.

WCF Services

WCF or Web services, not a big deal, let’s just call it WCF. Our service X.co provides you two WCF services that you can access:

The Squeeze service supports only one function that can be used to shorten (squeeze) long URLs. In fact, the Squeeze service provides other functions too, however, they are either deprecated or for the internal use of Go Daddy. The other service, the Reporting service, supports functions related to reports and analytics of short URLs (like clicks and referrer sites.)

Whatever service you like to use, you must reference it to your projects. To add a reference to a web service to your project, you can use one of two ways. The first and better way is to use Visual Studio. Right-click the Web References node under your project node in Solution Explorer and select Add Web Reference to launch the Add Web Reference dialog (see figure 3.)

Figure 3 - Solution Explorer - Add Web Reference
Figure 3 - Solution Explorer - Add Web Reference

The Add Web Reference dialog is now on the top of the IDE, the dialog might appear different in .NET 2.0 than higher versions (see figure 4 and figure 5.) Whatever, write the address of the service that you need to add, click Go so can Visual Studio read service description, write a good name in the Reference Name field that would be the namespace that groups service objects, and finally click Add Reference. Notice that we have used the name xcoapi for the Squeeze service, and xcoapirpt for the Reporting service.

Figure 4 - Add Web Reference Dialog in .NET 3.0+
Figure 4 - Add Web Reference Dialog in .NET 3.0+
Figure 5 - Add Web Reference Dialog in .NET 2.0
Figure 5 - Add Web Reference Dialog in .NET 2.0

Another approach to get the required source files for the service is to use the svcutil.exe tool that’s used internally by Visual Studio. This is a command tool that generates source files for web and WCF services. You can use this tool as follows:

svcutil.exe http://api.x.co/Squeeze.svc?wsdl /language=C#
svcutil.exe http://api.x.co/Squeeze.svc?wsdl /language=VB

Notice that we have included the address of the discovery (description) WSDL data of the services so that the tool can read it. Remember to select your language in the command.

Squeeze Service

The first function we have today and the only function of the Squeeze service (http://api.x.co/Squeeze.svc) is the Shorten() function that’s used to shorten long URL files. This function simply accepts 2 arguments:

  • url:
    The long URL to be shortened.
  • apiKey:
    The API key used to authenticate the call.

There’re other functions existing in the Squeeze service but they are either deprecated or reserved for internal use by Go Daddy.

After you ensure that a reference of the service is added to your project (check the previous section) you can start writing your code. The following function accepts the long URL and returned the shortened one that’s -at the time of this writing- is no more than 16 characters (e.g. http://x.co/8Gg8):

// C#

string Shorten(string url, string apiKey)
{
    using (xcoapi.Squeeze sq = new xcoapi.Squeeze())
    {
        return sq.Shorten(url, apiKey);
    }
}

Notice that web services consumes lots of system resources and you should release them as soon as you finish you work with them, that’s why we have used the C# using statement.

Reporting Service

The other service we have is the Reporting service (http://api.x.co/Reporting.svc) that offers you great deal of analytics and reporting functionalities that can be sorted in 3 areas:

  • Click count (the number of uses of the short URL)
  • Referrer sites (for the short URL)
  • Uses by locations (city, region, and country.)

This service supports 5 functions:

  • GetTotalMapClick():
    Returns total clicks (uses) of a short URLs.
  • GetMapClicksByDates():
    Returns clicks of a short URL made within a given time period grouped by days.
  • GetMapClicksByHour():
    Returns clicks of a short URL made today grouped by hours.
  • GetMapReferrersByDates():
    Returns referrer links made to the short URL within a given time period grouped by days.
  • GetMapLocationsByDates():
    Returns clicks of a short URL made within a given time period grouped by geographic location.

Those five functions are very similar in many ways. First, they all accept two required parameters:

In addition, the last four functions work the same way. They all return arrays of objects. GetMapClicksByHour() for instance returns the number of clicks made today grouped by hours each hour is represented by an object that contain the hour number besides the clicks made in that hour, and all objects are grouped inside one array.

The other functions GetMapClicksByDates(), GetMapReferrersByDates(), and GetMapLocationsByDates() work the same way and accept the same parameters except that they accept four additional parameters represent the begin and the end dates of the time period and whether the date parameters were set or leaved empty.

How can the four parameters help? You can define both and set the two flags to indicate that we need a specific time period. You can also set one of them and set its flag to indicate that you need to start from a specific day and get analytics till now. Notice that you can’t leave both empty.

The following code returns the total number of clicks for a specific short URL:

// C#

int GetTotalClicks(string shortCode, string apiKey)
{
    using (xcoapirpt.ReportingClient rpt = new xcoapirpt.ReportingClient())
    {
        return rep.GetTotalMapClick(apiKey, shortCode);
    }
}

And the following code is the same as the above except that it uses .NET 2.0:

// C#

int GetTotalClicks(string shortCode, string apiKey)
{
    using (xcoapirpt.Reporting rpt = new xcoapirpt.Reporting())
    {
        int totalClicks;
        bool succeeded;
        rep.GetTotalMapClick(apiKey, shortCode, out totalClicks, out succeeded);

        return succeeded ? totalClicks : -1;
    }
}

Notice the slight difference between the two calls (in .NET 2.0 and higher versions.) In .NET 2.0, the returned value is specified as an output parameter.

The following code is somewhat complex than the previous. The following code returns the refer links for our short URL:

// C#

xcoapirpt.ReferrerEventInfo[] GetReferrers
    (string shortUrl, string apiKey, out int totalClicks)
{
    using (xcoapirpt.Reporting rep = new xcoapirpt.Reporting())
    {
        xcoapirpt.ReferrerEventInfo[] results =
            rep.GetMapReferrersByDates(apiKey, shortUrl,
                DateTime.Now - new TimeSpan(7, 0, 0, 0, 0), true, DateTime.Now, true);

        totalClicks = 0;
        foreach (xcoapirpt.ReferrerEventInfo r in results)
            totalClicks += r.TotalSpecified ? r.Total : 0;

        return results;
    }
}

Notice how we specify the start and end date parameters and their flags to get only the last week analytics. Notice also the type of the array returned from the function and how we used it to get the required information.

RESTful Services

If you prefer not to use the WCF services, you can start with the REST interface provided to you by the kind-hearted WCF services. A RESTful service is simply a group of related web functions that has specific formats; some of return plaint text, some return XML data, and others return JSON.

Keep in mind that WCF services are supported natively by .NET framework and thus they are faster and easier to work with.

Squeeze Service

Not surprisingly, our RESTful Squeeze service is provided to us by the address http://api.x.co/Squeeze.svc. This service has two functions to shorten URLs, one is JSON, and the other is plain text.

The first function that returns plain text can be called using the following address:

http://api.x.co/Squeeze.svc/text/{apiKey}?url={url}

Now you have the address and ready with the input, the following function calls the previous function to shorten long URLs:

// C#

string Shorten(string url, string apiKey)
{
    WebRequest req = HttpWebRequest.Create(
        string.Format("http://api.x.co/Squeeze.svc/text/{0}?url={1}",
        apiKey, url));

    req.Timeout = 10000; // 10 seconds

    string shortUrl;
    System.IO.Stream stm;

    stm = req.GetResponse().GetResponseStream();

    using (System.IO.StreamReader rdr = new System.IO.StreamReader(stm))
    {
        return rdr.ReadToEnd();
    }
}

Reporting Service

Likewise, the Reporting service has the following address: http://api.x.co/Squeeze.svc. This service provides you with many functions like its WCF counterpart, however, all of them are JSON expect one is plain text. Because JSON is not natively supported by .NET Framework and thus requires the use of other 3rd party components (e.g. Json.NET) we won’t consider those endpoints. However, we have our total clicks function that returns plain text:

// C#

int GetTotalClicks(string shortCode, string apiKey)
{
    WebRequest req = HttpWebRequest.Create(
        string.Format("http://x.co/Reporting.svc/map/{0}/{1}/total",
        apiKey, shortCode));

    req.Timeout = 10000; // 10 seconds

    System.IO.Stream stm;

    stm = req.GetResponse().GetResponseStream();

    using (System.IO.StreamReader rdr = new System.IO.StreamReader(stm))
    {
        return int.Parse(rdr.ReadToEnd());
    }
}

Again, the short code is the only required piece of the short URL, you do not need to include the http://x.co/ (actually, you can’t!)

Source Code

Download the source code files from here.

What’s next

Consider reading more about URL shortening services here.

Consuming URL Shortening Services – bit.ly

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Read more about URL shortening services here.

Source- Elsheimy.Samples.ShortenSvcs.zip

Contents

Contents of this article:

  • Contents
  • Overview
  • Introduction
  • API
    • Overview
    • Function Explanation
    • Shortening Function
    • Expanding Function
    • Validation Function
    • Stats Function
    • Lookup Function
    • Info Function
    • Authentication Function
  • JSON Support
    • Sample
    • Where to go next

    Overview

    This is a very hot article that you can’t leave without checking it first. This article is talking about the most popular and powerful URL shortening service ever, bit.ly.

    Today, we are going to talk about bit.ly API, its functions, and how you can access them from your .NET application.

    Don’t forget to download the sample code at the end of the article.

    Let’s go!

    Introduction

    Today we are going to talk about the most popular yet most powerful URL shortening service ever in the web. Yes you guessed, it is bit.ly.

    Of course this service is well-known enough and we don’t need to describe it or talk about its features, so we’ll dig into the API immediately.

    API

    Overview

    There’re few things that you should keep in mind about bit.ly API:

    • REST API:

    The bit.ly API is a REST web service; means that it’s a collection of HTTP endpoints each accessed by a simple address filled with arguments the function (endpoint) requires the way you fill up query strings of a web page. Actually, you don’t need to care about REST web services or HTTP endpoints; you just need to know how to call those functions (simply, to access those addresses programmatically.)

    Yet, the current and only version of the API is version 3 and that can be accessed using the following address:

    http://api.bit.ly/v3/%5Bfunction_name%5D?%5Bargs%5D

    Simply, substitute function_name with the name of the function you need to call, and replace args with function arguments.

    Notice that you can try any function by just typing the address into the browser and navigating to the results.

    • Functions:

    The API provides you with lots of functions that satisfy your application needs. The following list contains the functions available:

    • Shorten:
      Used to shorten a long URL.
    • Expand:
      Used to expand the URL; to get the original long URL from the short one.
    • Validate:
      Used to validate a username and his API key.
    • Clicks:
      Used to retrieve stats (number of clicks) about the short URL specified.
    • Lookup:
      Used to check a long URL if exists in the database, i.e., if it has been shortened before.
    • Info:
      Used to retrieve information about the URL (e.g. the user created it, page title, etc.)
    • Authenticate:
      Used to check if a username and password are valid. Access restricted, more information available later at the end of this article.

    As you see, the API of bit.ly is the most sophisticated yet powerful API compared to the APIs of the other URL shortening services.

    • Input Arguments:

    Any URL passed to a function must be encoded first to eliminate the ‘#’, ‘?’, ‘=’ and other problematic characters in the URL. For encoding a URL, the function System.Net.Uri.EscapeUriString() is very sufficient.

    There’re three main required arguments that are used by all functions:

    • login:
      Username.
    • apiKey:
      The key used to authenticate the user access to the API.
    • format:
      The format (type) of returned data from functions.

    Those three are required by all functions and you cannot work without one of them.

    • Authentication:

    All functions require user authentication. The user can prove his identity using his login name (username) and his API key (not his password.) You can get your API key by accessing the page http://bit.ly/a/account (after logging on to your account) or directly from http://bit.ly/a/your_api_key.

    One of the hot features of the API is that it provides you a demo user that can be used in your API training, the information of that user is as follows:

    Username: bitlyapidemo

    API Key: R_0da49e0a9118ff35f52f629d2d71bf07

    You might face problems with this account like violation of rate limits and many other problems, and that because it’s used by many users in the same time. Therefore, it’s recommended that you use another account.

    • Supported Formats:

    The API supports two formats of its returned data, XML and JSON (the default.) Yes it supports plain text too, but it’s not supported by all functions. XML data is easily manipulated by XML, so we’ll concentrate on XML besides the plain text format of course.

    • Handling Errors:

    If the function failed and you have specified the format as Plain Text (txt) in the call, you get an exception thrown in your code. If the format was XML, you can check the returned data for whether the function succeeded or not.

    The XML data returned from functions must follow this schema:

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <status_code />
        <status_txt />
        ...
    </response>

    Here we have status_code set to the value 200 if the function succeeded and to the error code if the function failed. The status_txt describes the status of the function, it’s set to ‘OK’ if the function succeeded and to the error description if the function failed.

    The rest of the XML data is defined based on the function.

    • Preferred Domain:

    You have the option to use one of two domains, http://bit.ly and http://j.mp (new,) both offer you the same functionality and the same flexibility, however, the first counts to 20 characters while the other counts to only 18. (The domain can be set in the shortening function in the argument domain.)

    Keep in mind that the code just after the domain name (e.g. bnPuEX of http://bit.ly/bnPuEX) is called Hash and it is exactly 6 characters (case-sensitive.)

    There’re two types of hash, each short URL has many hashes:

    • User Hash:
      That hash of the URL generated for a given user shortened the URL. That means that a long URL might have more than one user hash equals to the number of users shortened that URL. (More than one hash means more than one short URL.)
    • Global Hash:
      A hash that is shared by all users for the same short URL.

    Thus, a short URL has only one global hash, but it might have more than one user hash (for each user shortened the same long URL.)

    • Rate Limits:

    You cannot think about making thousands of function calls every hour, access to the API is limited for each user on an hourly base. Limits are very sufficient for your application, but it’s going not to be sufficient if you are willing to spam the service or to drop it!

    Function Explanation

    Now we are going to talk about each function and how you can call it.

    First, get your API key that will be used to authenticate your calls to the API. If you need to bother yourself and to clog your application use the demo API user bitlyapidemo that have the API key R_0da49e0a9118ff35f52f629d2d71bf07.

    Shortening Function

    The first function we are going to talk about today is the shortening function, shorten. This function has the following address http://api.bit.ly/v3/shorten (as you expected) and is used to shorten long URLs. Besides main arguments key, apiKey, and format, it takes two more:

    • longUrl:
      The long URL to be shortened.
    • domain:
      Optional. The preferred domain, bit.ly or j.mp.

    You can get hands on this function and try it simply by navigating to the results of the following URL:

    http://api.bit.ly/v3/shorten?login=bitlyapidemo&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07 &format=txt&longUrl=http://JustLikeAMagic.com

    This call simply tries to shorten the URL http://JustLikeAMagic.com by using credentials of the demo API user (substitute the current information with your own.) The format is set to plain text.

    You can also use change the format to XML and get output like this:

    <?xml version="1.0" encoding="utf-8"?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <url>http://bit.ly/bO9TgE</url>
            <hash>bO9TgE</hash>
            <global_hash>9gSDEU</global_hash>
            <long_url>http://JustLikeAMagic.com&lt/long_url>
            <new_hash>0</new_hash>
        </data>
    </response>

    Notice that the status code is 200 that means that everything went ‘OK’. Notice that we have 5 elements:

    • url:
      The long URL generated.
    • hash:
      The user hash string.
    • global_hash:
      The globally shared hash. Can be used to browse to the URL too, it would be counted in the global statistics but not in user’s.
    • long_url:
      The original URL.
    • new_hash:
      Equals to 1 if this is the first time that URL being shortened (using the bit.ly service of course,) or 0 otherwise.

    Now, let’s code! The following function accepts a long URL and user API credentials and tries to shorten the URL using our shortening function.

    Don’t forget to add using statements to namespaces System.IO, System.Net, and System.Xml to that code and to the other code demonstrated in this article.

    // C#
    
    string Shorten(string url, string login, string key, bool xml)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/shorten?" +
            "login={0}&apiKey={1}&format={2}&longUrl={3}",
            login, key, xml ? "xml" : "txt", url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        // if the function fails and format==txt throws an exception
        Stream stm = req.GetResponse().GetResponseStream();
    
        if (xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(stm);
    
            // error checking for xml
            if (doc["response"]["status_code"].InnerText != "200")
                throw new WebException(doc["response"]["status_txt"].InnerText);
    
            return doc["response"]["data"]["url"].InnerText;
        }
        else // Text
            using (StreamReader reader = new StreamReader(stm))
                return reader.ReadLine();
    }

    Take notice of the mechanism used to check for errors.

    Expanding Function

    The next function we have is the function that is used to expand a URL, i.e., to get the long URL from the short one. Obviously, this function is called expand and it accepts the short URL shortUrl besides the three main arguments.

    Likewise, calling this function generate a data based on the function format, txt, xml, or json. The following XML data is generated when the function is called while the format is set to xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <entry>
                <short_url>http://bit.ly/bnPuEX</short_url>
                <long_url>http://justlikeamagic.com</long_url>
                <user_hash>bnPuEX</user_hash>
                <global_hash>bdE96m</global_hash>
            </entry>
        </data>
    </response>

    Now you can see the two hashes, user_hash and global_hash, and the two lend the user to your page (although the access is counted differently.)

    Now, let’s code! The following function retrieves the long URL from the short one:

    // C#
    
    string Expand(string url, string login, string key, bool xml)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/expand?" +
            "login={0}&apiKey={1}&format={2}&shortUrl={3}",
            login, key, xml ? "xml" : "txt", url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        // if the function fails and format==txt throws an exception
        Stream stm = req.GetResponse().GetResponseStream();
    
        if (xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(stm);
    
            // error checking for xml
            if (doc["response"]["status_code"].InnerText != "200")
                throw new WebException(doc["response"]["status_txt"].InnerText);
    
            return doc["response"]["data"]["entry"]["long_url"].InnerText;
        }
        else // Text
            using (StreamReader reader = new StreamReader(stm))
                return reader.ReadLine();
    }

    Validation Function

    The function validate is used to check if another username and API key pair is valid. For this function to work, you should use valid API credentials to check for the other credentials if they are valid or not. Therefore, you are going to use two additional arguments for the additional credentials, x_login and x_apiKey.

    This function doesn’t support plain text format. If XML was used, the function returns data like the following:

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <valid>0</valid>
        </data>
    </response>

    The valid element is set to 1 if the credentials were OK or 0 otherwise.

    And this is our C# function that validates user API credentials:

    // C#
    
    string Validate(string login, string key,
        string xLogin, string xKey, bool xml)
    {
        string reqUri =
            String.Format("http://api.bit.ly/v3/validate?" +
            "login={0}&apiKey={1}&x_login={4}&x_key={5}&format={2}" +
            login, key, xLogin, xKey, xml ? "xml" : "txt");
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        // if the function fails and format==txt throws an exception
        Stream stm = req.GetResponse().GetResponseStream();
    
        if (xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(stm);
    
            // error checking for xml
            if (doc["response"]["status_code"].InnerText != "200")
                throw new WebException(doc["response"]["status_txt"].InnerText);
    
            return int.Parse(doc["response"]["data"]["valid"]) == 1 ? true : false;
        }
        else // Text
            using (StreamReader reader = new StreamReader(stm))
                return int.Parse(reader.ReadLine()) == 1 ? true : false;
    }

    Stats Function

    This function is used to get stats about the short URL; the stats are represented in two values, user clicks and global clicks. User clicks value is the number of access times made to that user link. Global clicks value is the number of access times made from all short URLs (from all users) refer to the same address (almost like user hashes and global hash.)

    The function only accepts the short URL, shortUrl, besides the three main arguments. The data returned from the function is almost like this (in XML):

    <?xml version="1.0" encoding="utf-8" ?>
    <response>
        <status_code>200</status_code>
        <data>
            <clicks>
                <short_url>http://bit.ly/bnPuEX</short_url>
                <global_hash>bdE96m</global_hash>
                <user_clicks>0</user_clicks>
                <user_hash>bnPuEX</user_hash>
                <global_clicks>0</global_clicks>
            </clicks>
        </data>
        <status_txt>OK</status_txt>
    </response>

    The following C# function is used to retrieve number of access times for the current user and for all users:

    // C#
    
    int GetClicks(string url, string login, string key, out int globalClicks)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/clicks?" +
            "login={0}&apiKey={1}&shortUrl={2}&format=xml" +
            login, key, url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        Stream stm = req.GetResponse().GetResponseStream();
    
        XmlDocument doc = new XmlDocument();
        doc.Load(stm);
    
        // error checking for xml
        if (doc["response"]["status_code"].InnerText != "200")
            throw new WebException(doc["response"]["status_txt"].InnerText);
    
        XmlElement el = doc["response"]["data"]["clicks"];
        globalClicks = int.Parse(el["global_clicks"].InnerText);
        return int.Parse(el["user_clicks"].InnerText);
    }

    Lookup Function

    This function is used with long URLs to check whether they have been shortened before, and if so, the function returns the short URLs.

    If the long URL was found in service database, XML data like this is returned:

    <?xml version="1.0" encoding="utf-8" ?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <lookup>
                <url>http://JustLikeAMagic.com</url>
                <short_url>http://bit.ly/9gSDEU</short_url>
                <global_hash>9gSDEU</global_hash>
            </lookup>
        </data>
    </response>

    Otherwise, you get another form of XML data:

    <?xml version="1.0" encoding="utf-8" ?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <lookup>
                <url>http://JustLikeAMagic.com/books</url>
                <error>NOT_FOUND</error>
            </lookup>
        </data>
    </response>

    The following C# function looks-up a URL and returns its short URL if found:

    // C#
    
    string Lookup(string url, string login, string key)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/lookup?" +
            "login={0}&apiKey={1}&url={2}&format=xml" +
            login, key, url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        Stream stm = req.GetResponse().GetResponseStream();
    
        XmlDocument doc = new XmlDocument();
        doc.Load(stm);
    
        // error checking for xml
        if (doc["response"]["status_code"].InnerText != "200")
            throw new WebException(doc["response"]["status_txt"].InnerText);
    
        if (doc["response"]["data"]["lookup"]["error"] == null)
            return null; // not found
    
        return doc["response"]["data"]["lookup"]["short_url"].InnerText;
    }

    Info Function

    The info function is used to retrieve information about the current short URL. This function returns XML data like the following:

    <?xml version="1.0" encoding="utf-8" ?>
    <response>
        <status_code>200</status_code>
        <status_txt>OK</status_txt>
        <data>
            <info>
                <short_url>http://bit.ly/bnPuEX</short_url>
                <global_hash>bdE96m</global_hash>
                <user_hash>bnPuEX</user_hash>
                <created_by>elsheimy</created_by>
                <title>Just Like a Magic</title>
            </info>
        </data>
    </response>

    Besides link hashes, it returns the name of user who created it and the page title.

    And this is our C# function that retrieves that information:

    // C# Code
    
    string GetInfo(string url, string login, string key, out string createdBy)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/info?" +
            "login={0}&apiKey={1}&shortUrl={2}&format=xml" +
            login, key, url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        Stream stm = req.GetResponse().GetResponseStream();
    
        XmlDocument doc = new XmlDocument();
        doc.Load(stm);
    
        // error checking for xml
        if (doc["response"]["status_code"].InnerText != "200")
            throw new WebException(doc["response"]["status_txt"].InnerText);
    
        XmlElement el = doc["response"]["data"]["info"];
        createdBy = el["created_by"].InnerText;
        return el["title"].InnerText;
    }

    Authentication Function

    This is the last function today, the authenticate function. This function is used to check whether a username and a password are valid. Although this function and the validation function work the same way, there’s a big difference. The validation function checks for API credentials, the username and the API key, while this function checks for login information, the username and the password. Another big difference is that this function is currently access-restricted and you cannot use it before asking for permission from api@bit.ly.

    This function accepts two addition parameters, the username x_login and the password x_password.

    This function is called in a very specific way. You add arguments in the body of your request. In addition, the request is made by the method POST.

    If the function succeeded you get the API key for that user. For example:

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <status_code>200</status_code>
        <data>
            <authenticate>
                <username>bitlyapidemo</username>
                <successful>1</successful>
                <api_key>R_0da49e0a9118ff35f52f629d2d71bf07</api_key>
            </authenticate>
        </data>
        <status_txt>OK</status_txt>
    </response>

    Otherwise, the successful element is set to 0 and no other information is available:

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <status_code>200</status_code>
        <data>
            <authenticate>
                <successful>0</successful>
            </authenticate>
        </data>
        <status_txt>OK</status_txt>
    </response>

    The next C# function tries to authenticate a given user and retrieve his API key (Notice how to set information in the body of the request):

    // C#
    
    string Authenticate(string login, string key, string xLogin, string xPassword)
    {
        string reqUri = "http://api.bit.ly/v3/authenticate";
        string body =
            string.Format("login={0}&apiKey={1}&x_login={2}" +
            "&x_password={3}&format=xml",
            login, key, xLogin,xPassword);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000;
        req.Method = "POST";
    
        StreamWriter writer = new StreamWriter(req.GetRequestStream());
        writer.WriteLine(body);
    
        Stream stm = req.GetResponse().GetResponseStream();
        XmlDocument doc = new XmlDocument();
        doc.Load(stm);
    
        // error checking for xml
        if (doc["response"]["status_code"].InnerText != "200")
            throw new WebException(doc["response"]["status_txt"].InnerText);
    
        XmlElement el = doc["response"]["data"]["authenticate"];
        if (el["successful"].InnerText == "1")
            return el["api_key"].InnerText;
        else
            return null;
    }

    JSON Support

    We have been talking about the API and its support for XML and plain text formats and we missed the third one (is also the default,) that is JSON (JavaScript Object Notation.) Although XML and plain-text are enough and sufficient for most applications, and they’re very easy too, there’re some times when you are forced to work with JSON (some web services support only JSON data.) At least for completeness’ sake, we need to know how to handle JSON data when we have it in our hands.

    Worth mentioning that JSON is not supported by versions before .NET 3.5.

    First thing to know about bit.ly API is that you can get JSON data out of a function by passing the value json to the format parameter. Other way is to omit the format parameter completely, that’s because JSON is the default format that will be used when the format parameter not specified.

    Let’s take the shortening function as an example. Try calling the shortening function specifying json in the format parameter or removing the parameter completely:

    http://api.bit.ly/v3/shorten?login=bitlyapidemo&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07
    &format=json&longUrl=http://JustLikeAMagic.com

    When you call the previous function you get some results similar to those:

    {
        "status_code": 200, 
        "status_txt": "OK", 
        "data":
        {
            "long_url": "http://justlikeamagic.com",
            "url": "http://bit.ly/bnPuEX",
            "hash": "bnPuEX",
            "global_hash": "bdE96m",
            "new_hash": 0
        }
    }

    Can you notice the similarities between the structure of this JSON-formatted data and the XML-formatted data we have seen earlier? Actually, the structure is the same, there’s no difference except how data is formatted.

    Looking at this JSON snippet we can see that it’s just a structure contains a few members, every member has a name and value both separated by a colon (:) and each surrounded by double quotes, members are separated by commas (,), and the whole structure is surrounded by curly brackets. Worth mentioning that the data member is a compound data member, means that it defines some other members inside it.

    The first step in handling JSON data is to create .NET classes/structures from the JSON code keeping the same structure definitions and parameter names. For our example, we need to create the following classes:

    C#
    
        class ShortUrl
        {
            public int status_code;
            public string status_txt;
            public ShortUrlData data;
        }
    
        class ShortUrlData
        {
            public string long_url;
            public string url;
            public string hash;
            public string global_hash;
            public int new_hash;
        }

    Here comes the trick, the DataContractJsonSerializer class that’s available in the namespace System.Runtime.Serialization.Json which is available in System.Runtime.Serialization.dll for .NET 4.0 and in System.ServiceModel.Web.dll for .NET 3.5 (not available before version 3.5.)

    This class can be used in two ways: to serialize (i.e. generate JSON data from a structure) or to deserialize (i.e. return the data structure from JSON data) this data. To serialize some data you call any of the WriteXXX() functions (based on the data type,) to deserialize this data you call any of the ReadXXX() functions (based on the data type too.)

    After you add the right assembly to project references and import the namespace System.Runtime.Serialization.Json, you can now start coding:

    // C#
    
    ShortUrl Shorten(string url, string login, string key)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format("http://api.bit.ly/v3/shorten?" +
            "login={0}&apiKey={1}&format={2}&longUrl={3}",
            login, key, "json", url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 10000; // 10 seconds
    
        // if the function fails and format==txt throws an exception
        Stream stm = req.GetResponse().GetResponseStream();
    
        DataContractJsonSerializer con = 
            new DataContractJsonSerializer(typeof(ShortUrl));
        ShortUrl shortUrl = (ShortUrl)con.ReadObject(stm);
    
        return shortUrl;
    }

    Have fun with JSON!

    Sample

    Download the sample code here.

    Where to go next

    Read more about URL shortening services here.

    Consuming URL Shortening Services – Cligs

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Read more about URL shortening services here.

    Source- Elsheimy.Samples.ShortenSvcs.zip

    Contents

    Contents of this article:

    • Contents
    • Overview
    • Introduction
    • Description
    • API
      • Shortening URLs
      • Expanding URLs
    • Where to go next

    Overview

    This is another article that talks about URL shortening services. Today we are going to talk about Cligs, one of the popular shortening services on the web.

    Be prepared!

    Introduction

    Today we are talking about another popular shortening service; it’s Cligs, one of the most popular shortening services that provide lots of premium features for FREE.

    Enough talking, let’s begin the discussion.

    In December 2009, Cligs acquired by Mister Wong (a very nice bookmarking service.)

    Description

    How Cligs can help you? Cligs gives you plenty of features, including the following:

    • Shortening URLs (registered and non-registered users):
      You get a short URL that’s no more than 20 characters (Tweetburner is 22 and is.gd is only 18) including the domain http://cli.gs.
    • URL Management (registered users only):
      It allows you to manage your short URLs, to edit them, and to remove them if you like.
    • Real-time Analytics (registered users only):
      How many clicked your link, and when.
    • URL Previewing (registered and non-registered users):
      Preview the URL before opening it. Protects you from spam and unwanted sites.

    API

    Cligs provides you a very nice API with many advantages. The first advantage that we want to talk about is its simplicity. The API is very simple; it has just two functions, one for shortening URLs, and the other for expanding short URLs (to expand a URL means to get the long URL from the short one.)

    Another advantage of this API is that it allows you to shorten the URLs whether you are a registered user or not. Of course a registered user need to get an API key in order to link the API calls to his accounts so he can manage the links generated by the API and to watch the analytics.

    Shortening URLs

    The first function is used for shortening URLs and it’s called, create. This function has the following address:

    http://cli.gs/api/v1/cligs/create?url={1}&title={2}&key={3}&appid={4}

    The API is still in version 1, that’s why you see ‘v1’ in the address. This function takes four parameters, only the first one is required, other parameters are used for authentication:

    1. url:
      Required. The URL to be shortened.
    2. title:
      Optional. For authenticated calls only. The name that would be displayed on the short URL in your control panel (used for managing your URLs.)
    3. key:
      Optional. If you are a registered user and you want to link the API calls to your account, you’ll need to enter your API key here.
    4. appid:
      Optional. If you have used an API key, then you have to provide your application name that used to generate this API call (help users know the source of the link.)

    So how can you use this function? If this is an anonymous call (i.e. no authentication details provided,) just call the function providing the long URL in its single required argument.

    If you need to link this call to a specific account, then you’ll need an API key, which the user can get by signing in to his Cligs account, choosing ‘My API Keys’, then clicking ‘Create New API Key’ (if he doesn’t have one you.) The last step generates an API key that’s no exactly 32 characters (see figure 1.)

    Figure 1 - Creating API Keys, Cligs

    After you get the API key, you can push it to the function along with your application name in the appid argument.

    What about the title argument? For registered users, they can access their clig list (see figure 2) and see the URLs they shortened and the titles they choose above each of the URLs.

    Figure 2 - My Cligs, Cligs

    Now, let’s code! The following function makes use of the Cligs API to shorten URLs. It accepts three arguments, the long URL, the API key, and the application name. If the API key is null (Nothing in VB.NET,) the call is made anonymously, otherwise, the API key and the application name are used.

    // C#
    
    string Shorten(string url, string key, string app)
    {
        url = Uri.EscapeUriString(url);
        string reqUri =
            String.Format(@"http://cli.gs/api/v1/cligs/create?url={0}", url);
        if (key != null)
            reqUri += "&key=" + key + "&appid=" + app;
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 5000;
    
        try
        {
            using (System.IO.StreamReader reader =
                new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
            {
                return reader.ReadLine();
            }
        }
        catch (WebException ex)
        {
            return ex.Message;
        }
    }
    ' VB.NET
    
    Function Shorten(ByVal url As String, _
                     ByVal key As String, ByVal app As String) As String
    
        url = Uri.EscapeUriString(url)
        Dim reqUri As String = _
            String.Format("http://cli.gs/api/v1/cligs/create?url={0}", url)
        If key Is Nothing Then
            reqUri &= "&key=" & key & "&appid=" & app
        End If
    
        Dim req As WebRequest = WebRequest.Create(reqUri)
        req.Timeout = 5000
    
        Try
            Dim reader As System.IO.StreamReader = _
                New System.IO.StreamReader(req.GetResponse().GetResponseStream())
    
            Dim retValue As String = reader.ReadLine()
            reader.Close()
    
            Return retValue
        Catch ex As WebException
            Return ex.Message
        End Try
    
    End Function

    Expanding URLs

    The other function we have today is the expand function that’s used to get the long URL from the short one (e.g. to expand the short URL http://cli.gs/p1hUnW to be http://JustLikeAMagic.com.) This function is very simple and it has the following address:

    http://cli.gs/api/v1/cligs/expand?clig={1}

    This function accepts only a single argument, that’s the clig (short URL) to be expanded. The clig can be specified using one of three ways:

    • The clig ID. e.g. p1hUnW.
    • The raw URL. e.g. http://cli.gs/p1hUnW.
    • The encoded URL. e.g. http%3A%2F%2Fcli.gs%2Fp1hUnW.

    You can read more about URL encoding here.

    Now it’s the time for code! The following function takes a clig and returns its original URL:

    // C#
    
    string Expand(string url)
    {
        url = Uri.EscapeUriString(url);
        string reqUri = String.Format(@"http://cli.gs/api/v1/cligs/expand?clig={0}", url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 5000;
    
        try
        {
            using (System.IO.StreamReader reader =
                new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
            {
                return reader.ReadLine();
            }
        }
        catch (WebException ex)
        {
            return ex.Message;
        }
    }
    ' VB.NET
    
    Function Expand(ByVal url As String) As String
    
        url = Uri.EscapeUriString(url)
        Dim reqUri As String = _
            String.Format("http://cli.gs/api/v1/cligs/expand?clig={0}", url)
    
        Dim req As WebRequest = WebRequest.Create(reqUri)
        req.Timeout = 5000
    
        Try
            Dim reader As System.IO.StreamReader = _
                New System.IO.StreamReader(req.GetResponse().GetResponseStream())
    
            Dim retValue As String = reader.ReadLine()
            reader.Close()
    
            Return retValue
        Catch ex As WebException
            Return ex.Message
        End Try
    
    End Function

    Where to go next

    Some other articles about URL shortening services are available here.

    Consuming URL Shortening Services – Tweetburner (twurl)

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Read more about URL shortening services here.

    Source- Elsheimy.Samples.ShortenSvcs.zip

    Contents

    Contents of this article:

    • Contents
    • Overview
    • Introduction
    • Description
    • API
    • Where to go next

    Overview

    Just another article of the URL shortening services series.

    Today, we are going to talk about another hot and easy-to-use service, it’s Tweetburner. If you haven’t used it before, then it’s the time to.

    We’re going to discuss how to use Tweetburner first. After that, we’ll inspect its API and learn how to use it in your .NET application.

    Introduction

    Again, one of the most popular URL shortening services ever.

    Today is dedicated for Tweetburner (known as twurl,) one of the hot, simple, and easy-to-use shortening services that you can compare to is.gd.

    Description

    When you visit Tweetburner website (via http://tweetburner.com or http://twurl.nl,) you can see that it allows users to register to gain more functionalities (specifically, link analytics.) However, at the time of this writing, the account page is disabled for technical issues and nothing interesting would happen if you register there.

    One of the hot features of Tweetburner is that it allows you to post your links to twitter (you guessed) and friendfeed as soon as they’re shortened just click ‘Share this link’ before you leave the page.

    Figure 1 - Shortening a URL, Tweetburner

    Figure 2 - Sharing a URL, Tweetburner

    Unfortunately, you can’t benefit from this sharing feature programmatically, but of course, you can create your own routines.

    After shrinking your URL, you get a new short link about 22 characters long (18 in is.gd) prefixed with http://twurl.nl.

    API

    Actually, Tweetburner doesn’t help you with an API. Instead, it provides you with a simple web page (used for shortening URLs) that you can access it from your code and get your short URLs.

    Let’s try it! Browse to our key page, http://tweetburner.com/links, and push your long URL and click the shortening button.

    Figure 3 - Shortening Links API, Tweetburner

    So how you can access this page via your .NET application and fill in its single field? Let’s get the idea! If you check the API documentation page, you might find that you are required just to request information from that page, post it the required URL via a simple string included in the request body, link[url]={0} (where {0} is the long URL, and just wait for the response that would contain the short URL of course if the function succeed.

    Do you find that ‘link[url]={0}’ strange? Try this with me! Browse to our page, http://tweetburner.com/links, and save it as HTML in your PC (not required, just grab its HTML code.)

    Sure we are interested on this magical text box, so scroll down to its definition that looks like this:

    Notice that the text box is given the name ‘link[url]’, that’s why we push ‘link[url]={0}’ on the request body. Given that hot information, you can push any data to any web form, just get the information required.

    Now, let’s code! The next function browses to our page, http://tweetburner.com/links, pushes the long URL specified, and gets the short URL back from the server. (Remember to include the namespace System.Net for the code to work properly.)

    // C#
    
    string Short(string url)
    {
        url = Uri.EscapeUriString(url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://tweetburner.com/links");
        req.Timeout = 5000;
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
    
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes("link[url]=" + url);
        req.ContentLength = buffer.Length;
    
        System.IO.Stream ios = req.GetRequestStream();
        ios.Write(buffer, 0, buffer.Length);
    
        try
        {
    
            using (System.IO.StreamReader reader =
                new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
            {
                return reader.ReadLine();
            }
        }
        catch (WebException ex)
        {
            return ex.Message;
        }
    }
    ' VB.NET
    
    Function Shorten(ByVal url As String) As String
        url = Uri.EscapeUriString(url)
    
        Dim req As HttpWebRequest = _
            CType(WebRequest.Create("http://tweetburner.com/links"), HttpWebRequest)
        req.Timeout = 5000
        req.Method = "POST"
        req.ContentType = "application/x-www-form-urlencoded"
    
        Dim buffer() As Byte = _
            System.Text.Encoding.UTF8.GetBytes("link[url]=" + url)
        req.ContentLength = buffer.Length
    
        Dim ios As System.IO.Stream = req.GetRequestStream()
        ios.Write(buffer, 0, buffer.Length)
    
        Try
            Dim reader As System.IO.StreamReader = _
                New System.IO.StreamReader(req.GetResponse().GetResponseStream())
    
            Dim retValue As String = reader.ReadLine()
    
            reader.Close()
    
            Return retValue
        Catch ex As WebException
            Return ex.Message
        End Try
    End Function

    Notice that we have specified the POST method because it’s required if you are going to change some data in the server. It’s worth mentioning too that we have set the content type to application/x-www-form-urlencoded because it’s required if you are going to push data to a web form (it’s usually perfect for all web forms except file-uploads.)

    In addition, we have included the input required in the request stream.

    What’s next

    Some other articles about URL shortening services are available here.

    Consuming URL Shortening Services – is.gd

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Read more about URL Shortening Services here.

    Source- Elsheimy.Samples.ShortenSvcs.zip

    Contents

    Contents of this article:

    • Contents
    • Overview
    • Introduction
    • API
    • What’s next

    Overview

    Another article of our series that talks about accessing URL shortening services programmatically.

    This article is talking about is.gd shortening service, how you can use it, and how to access it via your C#/VB.NET application.

    Introduction

    is.gd is one of the most popular shortening services ever in the web because of its simple interface and its easy-to-use API.

    When you visit service website, http://is.gd, you can see that nothing easier from is.gd, just push your long URL into the text box and click the shortening button.

    API

    is.gd provides you a very simple easy-to-use API. This API contains only one function that’s used for shortening URLs. Another good thing is that this function doesn’t require any kind of authentication for users. Therefore, you need just to spam it with your long URL (as you did with the website.)

    This glorious function is called http://is.gd/api.php, it accepts only a single argument, longurl, which can be set to the long URL you need to shorten. When you call the function, it simply returns the shortened URL as plain text (no more overhead.)

    Now, let’s try this function. We’ll try to shorten the URL http://JustLikeAMagic.com with our function. First, connect the arguments, http://is.gd/api.php?longurl=http://JustLikeAMagic.com. Now copy this address and paste it into your favorite browser. If everything was OK, you should see the short URL after clicking €˜Go’ in the browser toolbar.

    Now, let’s do it in C# and VB.NET. Check the following function that tries to shorten long URLs via the id.gd API:

    // C#
    
    string Shorten(string url)
    {
        url = Uri.EscapeUriString(url);
        string reqUri = String.Format(@"http://is.gd/api.php?longurl={0}", url);
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
        req.Timeout = 5000;
    
        try
        {
            using (System.IO.StreamReader reader =
                new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
            {
                return reader.ReadLine();
            }
        }
        catch (WebException ex)
        {
            return ex.Message;
        }
    }
    ' VB.NET
    
    Function Shorten(ByVal url As String) As String
    
        url = Uri.EscapeUriString(url)
        Dim reqUri As String = _
            String.Format("http://is.gd/api.php?longurl={0}", url)
        Dim req As WebRequest = WebRequest.Create(reqUri)
        req.Timeout = 5000
    
        Try
            Dim reader As System.IO.StreamReader = _
                New System.IO.StreamReader(req.GetResponse().GetResponseStream())
    
            Dim retValue As String = reader.ReadLine()
            reader.Dispose()
    
            Return retValue
        Catch ex As WebException
            Return ex.Message
        End Try
    
    End Function

    Notice that we have used the function System.Net.Uri.EscapeUriString() to eliminate unacceptable characters from the URL by encoding them.

    Notice too that we have included our code in a Try-Catch block so we can catch exceptions before they blow up our application.

    What’s next

    Consider reading other articles in this series here.

    Consuming URL Shortening Services – Introduction

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Read more about URL shortening services here.

    Source- Elsheimy.Samples.ShortenSvcs.zip

    Contents

    Contents of this article:

    • Contents
    • Overview
    • Introduction
    • Accessing the API
    • Authentication
    • .NET Support
    • Encoding
    • Sample
    • Where to Go Next
    • Poll: What are your favorite URL shortening services?

    Overview

    This is the first article of our series that talks about accessing URL shortening services programmatically.

    Here we introduce new concepts like the REST API. We also have a brief discussion of URL shortening services APIs and how you can access them.

    In addition, we are going to talk about .NET support for the REST API and tools and techniques available that would help us during our journey through the API.

    A working example built using C# and WinForms is available at the end of this article.

    This article is the base for all other articles. Articles other than this discuss specific services and their APIs. We will make use of code and techniques discussed here throughout the rest of articles.

    Let’s go!

    Introduction

    URL shortening services are very popular these days since web addresses tend to be very long and very difficult to be exchanged via email or other micro-blogging services like Twitter.

    Today, there’re tenths of URL shortening services spread out all over the web. Most of them are listed in the following articles:

    In this series, we are going to talk about how to consume URL shortening services in your .NET application. In other words, we will discuss how to program URL shortening services; we mean how to access them programmatically. In addition, we will have a brief discussion of each service and its unique features.

    How we will go through this discussion? This is going to be a series of articles published regularly. Each article discusses a given shortening service from the following list (updated regularly, expect new services to be added):

    The preceding list may not be comprehensive, many other popular services exist. However, not all shortening services have APIs! The preceding list contains the shortening services we know that allow developers to consume their functionalities via an exposed API.

    Before we start with a specific service, let’s have a brief discussion of features of the API and how we can access them.

    Accessing the API

    Most APIs in the web are just REST (Representational State Transfer) web services. A REST web service is simply a collection of functions (HTTP endpoints) that can be used to retrieve data in a variety of formats (optional.)

    Given an endpoint (function) like http://ab.c/api/shrink, we could supply the required input arguments as query strings in the URL. For example, we could shorten the URL www.google.com using a call to the HTTP endpoint http://ab.c/api/shrink?url=www.google.com supplied with the required information. It is worth mentioning that every service has its own API functions and arguments. Although they all do the same thing (shortening the URL,) they differ in function and argument names.

    When you call a web function, you just end up with the results in the format used in that function (XML, Atom, JSON, etc.) The function could also return plain text! It’s all about the function documentation that you should check carefully before calling the function. In addition, the returned value from a function may also contain error details if the function didn’t success.

    Keep in mind that API calls are limited and you can’t just leave the shortening code in an end-less loop! Other limitations of specific APIs should be discussed later.

    Authentication

    Most URL shortening services allow users to consume the service without being registered, some of allow users to register, and others not. Many other services require users to be registered in order to use the service.

    Likewise, service APIs may or may not require user authentication. Some services give the user an API key that can be used in the authentication process. Other services require user to enter his login details in the API calls. Most use the API key approach.

    .NET Support

    Does .NET support the REST API? Sure! As long as REST web services are just collections of HTTP endpoints, we do not need to worry about accessing them from .NET since that the BCL offers us a bunch of classes (available in System.dll) that can help with HTTP requests and responses.

    In addition, we will rely heavily on classes of System.Xml.dll to handle the data returned from functions (we will make use of functions that support XML.)

    If we could write something in C# that calls our fake web function http://ab.c/api/shrink, we could end up with some code like this:

    // C#
    
    public void string Shorten(string url)
    {
        string reqUri = @"http://ab.c/api/shrink?url=" + url;
    
        WebRequest req = WebRequest.Create(reqUri);
        req.Timeout = 5000;
    
        XmlDocument doc = new XmlDocument();
        doc.Load(req.GetResponse().GetResponseStream());
    
        return HandleXml(doc);
    }
    ' VB.NET
    
    Function Shorten(ByVal url As String) As String
    
        Dim reqUri As String = "http://ab.c/api/shrink?url=" &amp; url
    
        Dim req As WebRequest = WebRequest.Create(reqUri)
        req.Timeout = 5000
    
        Dim doc As new XmlDocument()
        doc.Load(req.GetResponse().GetResponseStream())
    
        Return HandleXml(doc)
    
    End Function

    Encoding

    If the URL to shorten have special characters like ‘&’, ‘?’, ‘#’, or ‘ ‘, those characters should be handled first before the URL is sent to the shortening function.

    This special handling for URLs is usually called Percent-encoding or URL Encoding. This encoding replaces unsafe characters with their hexadecimal values preceded by percentage (‘%’) signs.

    There are many unsafe characters that should be percent-encoded including ‘$’, ‘+’, ‘&’, ‘:’, and ‘=’. A nice discussion of URL Encoding can be found in the article URL Encoding by Brian Wilson.

    Why unsafe characters are problematic? Consider the following example: we need to shorten the URL http://justlikeamagic.com/?s=twitter with our fake shortening service http://ab.c, we end up with a call to the function using the following address http://ab.c/api/shrink?url=http://justlikeamagic.com/?s=twitter. Now we have two ‘?’s!!!

    So how can we encode URLs? Simply use the EscapeUriString() function of System.Net.Uri class it would work well for us here. If you need a full-featured encoder; a procedure that would work for all and every situation, you will need to consider creating one yourself, or you can use this:

    // C#
    
    char[] _chars = new char[]
    {
         '%',
         '$' ,
         '&amp;',
         '+',
         ',',
         '/',
         ':',
         ';',
         '=',
         '?',
         '@',
         ' ',
         '"',
         '',
         '#',
         '{',
         '}',
         '|',
         '\',
         '^',
         '~',
         '[',
         ']',
         ''', };
    
    string EncodeUrl(string url)
    {
        for (int i = 0; i < _chars.GetUpperBound(0); i++)
            url = url.Replace(
                _chars[i].ToString(),
                string.Format("{0:X}", (int)_chars[i]));
    
        return url;
    }
    
    string DecodeUrl(string url)
    {
        for (int i = 0; i < _chars.GetUpperBound(0); i++)
            url = url.Replace(
                string.Format("{0:X}", (int)_chars[i]),
                _chars[i].ToString());
    
        return url;
    }

    ' VB.NET

    Private _chars() As String = _
    { _
    "%", _
    "$", _
    "&amp;", _
    "+", _
    ",", _
    "/", _
    ":", _
    ";", _
    "=", _
    "?", _
    "@", _
    " ", _
    "", _
    "”, _
    “#”, _
    “{“, _
    “}”, _
    “|”, _
    “”, _
    “^”, _
    “~”, _
    “[“, _
    “]”, _
    “‘”}

    Public Function EncodeUrl(ByVal url As String) As String
    For i As Integer = 0 To _chars.GetUpperBound(0) – 1
    url = url.Replace( _
    _chars(i).ToString(), _
    String.Format(“{0:X}”, CInt(_chars(i))))
    Next

    Return url
    End Function

    Public Function DecodeUrl(ByVal url As String) As String
    For i As Integer = 0 To _chars.GetUpperBound(0) – 1
    url = url.Replace( _
    String.Format(“{0:X}”, CInt(_chars(i))), _
    _chars(i))
    Next

    Return url
    End Function

    Sample

    Download the sample from here.

    Where to Go Next

    Now start with any shortening service you like (links are update regularly, new services will be available too):

    Or else, check our URL Shortening Services tag.

    Poll

    Serialization vs. Marshaling

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Overview

    Are you somewhat confused between Serialization and Marshaling? This writing would break this confusion up, it would give you a basic understanding of the process of Serialization and the process of Marshaling, and how you can get the most out of each.

    Serialization

    Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file, a memory buffer, or transmitted across a network connection to be “resurrected” later in the same or another computer environment. And this sequence of bits can be of any format the user chooses; however, they are usually formed as XML or binary.

    Serialization comes in many forms in .NET Framework, it can be observed in ADO.NET, Web services, WCF services, Remoting, and others.

    For example, calling the WriteXml() function of a DataSet serializes this DataSet into a XML file.

        ds.WriteXml("data.xml");

    And if we have such this structure:

        public struct User
        {
            public int id;
            public string name;
        }

    we can get the following results if we serialize a collection of that structure into XML:

    
    
        
            12
            Mark
        
        
            13
            Charles
        
        
            14
            John
        
    

    Serialization can be observed in Web and WCF services too. The request and parameter information for a function are serialized into XML, and when the function returns the response and the returned data too are serialized into XML. Actually, you don’t have to think about these XML data, CLR handles this for you.

    In the same vein, when it comes to Remoting, the sender and recipient must agree to the same form of XML data. That’s, when you send some data CLR serializes this data for you before it sends it to the target process. When the target process receives this XML data, it turns it back (deserializes it) to its original form to be able to handle it.

    Thus, the process of converting data structures and objects into series of bits is called Serialization. The reverse of this process, converting these bits back to the original data structures and objects, is called Deserialization.

    Therefore, the following ADO.NET line does deserializes the XML file:

        DataSet ds;
        ds.ReadXml("data.xml");

    And when your application receives response from the server or from another process, the CLR deserializes that XML data for you.

    So why XML is preferred over binary serialization? That’s because XML is text-based. Thus, it’s free to be transmitted from a process to another or via a network connection, and firewalls always allow it.

    Marshaling

    Marshaling is the process of converting managed data types to unmanaged data types. There’re big differences between the managed and unmanaged environments. One of those differences is that data types of one environment is not available (and not acceptable) in the other.

    For example, you can’t call a function like SetWindowText() -that sets the text of a given window- with a System.String because this function accepts LPCTSTR and not System.String. In addition, you can’t interpret (handle) the return type, BOOl, of the same function, that’s because your managed environment (or C# because of the context of this writing) doesn’t have a BOOL, however, it has a System.Boolean.

    To be able to interact with the other environment, you will need to not to change the type format, but to change its name.

    For example, a System.String is a series of characters, and a LPCTSTR is a series of characters too! Why not just changing the name of the data type and pass it to the other environment?

    Consider the following situation. You have a System.String that contains the value €œHello€:

    System.String str = "Hello";

    The same data can be represented in an array of System.Char too, like the following line:

    System.Char[] ch = str.ToCharArray();

    So, what is the difference between that System.String variable and that System.Char array? Nothing. Both contain the same data, and that data is laid-out the same way in both variables. That’s what Marshaling means.

    So what is the difference between Serialization and Marshaling?

    C# has a System.Int32, and Windows API has an INT, and both refer to a 32-bit signed integer (on 32-bit machines.) When you marshal the System.Int32 to INT, you just change its type name, you don’t change its contents, or lay it in another way (usually.) When you serialize a System.Int32, you convert it to another form (XML for instance,) so it’s completely changed.

    Summary

    Look, after I get back to Wikipedia documentation for Marshaling, I realized that my answer was so specific to C#!

    I mean that, Marshaling is a very general term used to describe transformations of memory. Theoretically, it’s more general than Serialization. In Python for instance, the terms Marshaling and Serialization are used interchangeably. There (in Python,) Marshaling = Serialization, and Serialization = Marshaling, there’s no difference. In computer methodology, there’s a silent difference between Marshaling and Serialization (check the Wikipedia definition.)

    So what is that System.MarshalByRefObject class? Why that name -specifically- was used? First, System.MarshalByRefObject class allows objects to be passed by reference rather than by value in applications that use Remoting.

    Personally, I like to say that Microsoft .NET Framework team’s name was very scientific when they have called that object “MarshalByRefObject” with respect to that silent difference between serialization and marshaling or maybe that name was derived from Python, dunno!

    After all, we should keep in mind that in .NET methodology, there’s a big difference between Serialization and Marshaling, Marshaling usually refers to the Interop Marshaling. In .NET Remoting, it refers to that serialization process.

    By the way, Marshalling is so named because it was first studied in 1962 by Edward Waite Marshall, then with the General Electric corporation.

    That’s all.

    Have a nice day!

    Creating a Simple Twitter Client Application

    هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

    Code: Geming.twitoo.msi

    Contents

    Contents of this writing:

    • Contents
    • Overview
    • Introduction
    • Twitter API
      • What Twitter API is
      • API Documentation
      • Things to be Kept into mind
    • API Methods
      • Method Address
      • Methods with Arguments
      • Methods Require Authentication
    • Twitter and .NET
      • Accessing the API
      • Authentication
      • Encoding URIs
      • Business Objects
      • Retrieving Data
    • twittoo; Sample Application
      • Snapshots
      • Description
      • Interface
      • URL Shortening
      • Download

    Overview

    This writing discusses the Twitter API and how you can utilize it in your managed application. It begins by a brief discussion of the API and the methods used. After that, it digs into the discussion of how you can utilize the API into your application with help of code samples and examples. At the end of this writing, there’s a nice open-source Twitter client application available for download. Worth mentioning that this article focuses on the REST API set of Twitter, specifically XML endpoints.)

    Introduction

    Today, we are talking about Twitter as it is one of the most famous social networking services. This article discusses how you can create Twitter clients using .NET Framework. Oh, before we start, I’d like to introduce you my twitter account first; it’s @elsheimy.

    Twitter API

    What Twitter API is

    Before we dig into the discussion of Twitter API we need to know first what the Twitter API is.

    Twitter API is a set of endpoints (or methods) that allow applications to work with Twitter data.

    Twitter API consists of three parts:

    • Two REST APIs:
      • REST API:
        This is the core API set; it allows developers to access core Twitter data, it contains most (if not all) of the methods and functions you would use to utilize Twitter data in your application, and it supports (mostly) three formats (or endpoints) for each method: XML, Atom, and JSON formats.
      • Search API:
        Fully integrating search methods allows you to search for tweets based on specific criteria and to search for daily/weekly hot trends. It supports only the JSON format. This set of API was originally developed by Summize, Inc. and integrated into the Twitter API. (Twitter is looking forward to unify the REST API.)
    • Streaming API:
      A set of API methods that allow near-realtime access to various subsets of Twitter public statuses. All methods are in JSON format, no XML or ATOM endpoints available.

    Actually, the REST API would be very sufficient for you unless you find it easier to handle the JSON format.

    It is worth mentioning that the REST API provides very handful and sufficient search methods that your application can use. If you need more searching capabilities (like searching for tweets that confirm to a set of criteria,) you can dig into the REST Search API.

    You are not required to stick to a specific set of API methods. You can mix the methods you like from the three APIs.

    Wikipedia: REST (Representational State Transfer) is a style of software architecture for distributed hypermedia systems such as the World Wide Web.

    Wikipedia: JSON (JavaScript Object Notation) is a lightweight text-based open standard designed for human-readable data interchange based on the JavaScript programming language.

    Wikipedia: Atom Publishing Protocol (AtomPub or APP) is a simple HTTP-based protocol for creating and updating web resources.

    This writing focuses on the XML endpoints of the REST API.

    API Documentation

    Twitter has with a very nice API documentation that documents each and all methods and endpoints of the three parts of the API. This documentation can be found here: http://apiwiki.twitter.com.

    To avoid duplication, we are not going to discuss the Twitter API again in this writing; it is already documented and available for all users. Instead, we will take a brief look at the API and discuss how we can utilize it in our .NET application. For simplicity, we will focus on XML endpoints. Therefore, all of our code would rely on the XML features of .NET Framework 2.0 (i.e. System.Xml.dll library.) Oh, you are free to write the code the way you like (e.g. integrating LINQ for XML into the code.)

    Now, we are going to look inside the Twitter API.

    Things to be Kept into Mind

    There are some basics of the Twitter API that a developer should keep into his mind.

    • Calls to the Twitter API are limited:
      Don’t expect to post unlimited updates or to follow thousands of users in just an hour! Many methods have a call limit (hourly/daily.) For example, at the time of this writing, you have only 150 API requests per hour, further requests would return an exception. In addition, you can send only 1,000 updates and 250 direct messages per day (can we remove this word ‘only€?) You can check Twitter limits here.
    • Every endpoint has its HTTP methods that need to be set (e.g. GET, POST, and DELETE) in the request. The documentation of each endpoint lists the HTTP methods required for that endpoint. For more information about HTTP and HTTP methods check the RFC 2616 Section 9 document.
    • Some methods (like methods send updates) require user authentication and others not. Authentication is discussed soon.

    API Methods

    The following is a discussion about Twitter API methods and how you can call them.

    Method Address

    Every method has an address (i.e. URI). The address of a method is something like that: http://api.twitter.com/1/statuses/public_timeline.format (for the statuses/public timeline method.) We replace the format field with the format we like to work with (e.g. xml, atom, json.)

    Now, try to copy the method address http://api.twitter.com/1/statuses/public_timeline.xml and paste it into your browser. You should get something like that:

    
        
            Wed Apr 14 19:32:07 +0000 2010
            12179999634
            35 Ingenious Examples of Footwear - http://su.pr/1JxMAr
            <a href="http://apiwiki.twitter.com/" rel="nofollow">API</a>
            false
            
            
            false
            
            
                15736190
                Smashing Magazine
                smashingmag
                Freiburg, Germany
                Vitaly Friedman, editor-in-chief of SmashingMagazine.com ...
                http://a3.twimg.com/profile_images/572829723/...
                http://www.smashingmagazine.com
                false
                166019
                B2DFDA
                333333
                f51616
                ffffff
                eeeeee
                394
                Tue Aug 05 14:00:40 +0000 2008
                4
                -10800
                <time>Greenland</time>
                http://s.twimg.com/a/...
                true
                false
                true
                false
                false
                8703
                en
                false
            
            
            
            
            
        
        . . .
    

    This method returns the 20 most recent statuses from arbitrarily-selected non-protected Twitter users; this list is called the Public Timeline. Because we have selected the XML format (or endpoint) we end up with XML data.

    From the data returned we can extract the structure of statuses and users. Twitter API is good enough; it uses the same structure for all data returned. In other words, all methods (in the REST API, remember?) use the same structure (i.e. schema) to represent status and user objects. Those structures are covered soon.

    Methods with Arguments

    Most of methods accept arguments, some are optional and others are required. An example of a function requires a single argument is the users/show method that returns profile information about a specific user.

    This function accepts one of three arguments:

    • id:
      The ID or screen name of the user.
    • user_id:
      The ID of the user.
    • screen_name:
      The screen name of the user.

    We set arguments the same way we set web pages query strings. Considering my twitter account @elsheimy as an example, we could query user profile using one of four ways:

    All of the four calls return the same results that should be like this:

    
        19645411
        Mohammad Elsheimy
        Elsheimy
        KB, Egypt
        Technology evangelist from Egypt born in 1991
        http://a1.twimg.com/profile_images/833061500/...
        http://justlikeamagic.com
        false
        278
        DBE9ED
        333333
        CC3366
        E6F6F9
        DBE9ED
        179
        Wed Jan 28 10:47:36 +0000 2009
        7
        7200
        <time>Cairo</time>
        http://s.twimg.com/a/1271811071/...if
        false
        
        true
        false
        
        1877
        en
        false
        
            Wed Apr 21 16:21:46 +0000 2010
            12585240751
            I'm reading this, it's really hot: #RFC 2616 - Hypertext Transfer Protocol ...
            <a href="http://bit.ly" rel="nofollow">bit.ly</a>
            false
            
            
            false
            
            
            
            
            
        
    

    As you can see, it returns user information and the last update of that user. Notice that the structure of the data is the same in all methods.

    Methods Require Authentication

    Some methods require user authentication. Examples are functions update status, send direct messages, retrieve friends’ timeline, etc.

    Let’s take an example. Bring up your browser and browse to the address of statuses/friends timeline method that returns user’s friends’ timeline, http://api.twitter.com/1/statuses/friends_timeline.xml. A small window like this should appear that asks you your Twitter username and password.

    Figure 1. IE Authentication

    Provide your Twitter username and password to pass to the results. If authentication was OK, you should receive the most recent 20 statuses of your friend timeline in the same structure (schema) as the Public Timeline method. On the other hand, if the authentication process failed, you should receive an error:

    
        /1/statuses/friends_timeline.xml
        Could not authenticate you.
    

    Let’s consider another example, the direct_messages/new method. This function sends a new direct message to a specific user from the current user authenticated.

    This function accepts two required arguments:

    • user:
      The ID or screen name of the recipient user. You can use one of two arguments in place of this argument:

      • screen_name:
        Screen name of the user.
      • user_id:
        The ID of the user.
    • text:
      Message body, not longer than 140 UTF-8-encoded characters.

    The following two calls send the same message (‘hi, how is it going€) to the same user:

    Notice that we need to encode arguments before we pass them to the server.

    Because this function updates data, it requires HTTP POST method. Therefore, you won’t be able to try it from your browser unless your browser allows you to set HTTP methods in the request.

    If the function succeeded, it should return the message object that has been sent, and it should be like this:

    
        88619848
        1401881
        all your bases are belong to us.
        7004322
        Wed Apr 08 20:30:04 +0000 2009
        dougw
        igudo
        
            1401881
            Doug Williams
            dougw
            San Francisco, CA
            Twitter API Support. Internet, greed, users, dougw ...
            http://s3.amazonaws.com/twitter_production/...
            http://www.igudo.com
            false
            1036
            9ae4e8
            000000
            0000ff
            e0ff92
            87bc44
            290
            Sun Mar 18 06:42:26 +0000 2007
            0
            -18000
            <time>Eastern Time (US &amp; Canada)</time>
            http://s3.amazonaws.com/...
            false
            3394
            false
            false
            true
        
        
            7004322
            Doug Williams
            igudo
            North Carolina
            A character.
            http://s3.amazonaws.com/...
            http://www.igudo.com
            false
            19
            69A1AA
            000000
            F00
            ACBEC1
            8A8F85
            3
            Thu Jun 21 21:16:21 +0000 2007
            0
            -18000
            <time>Eastern Time (US &amp; Canada)</time>
            http://static.twitter.com/...
            false
            382
            false
            true
            true
        
    

    Notice that the sender and recipient are just user objects. It is worth mentioning that the direct_messages function return a list of direct_message objects (like the timeline functions that return list of status objects.)

    Twitter and .NET

    Now, you have a solid understanding of the Twitter API and how you can access it. Now, let’s utilize this API into our .NET applications.

    Accessing the API

    To access the API from your .NET application you need to create a HTTP request and send it to the server and wait for server response. Let’s consider an example. The following code snippet connects to the server and retrieves a System.Xml.XmlDocument that contains the returned data.

    // C# Code
    
    public static Main()
    {
        GetResponse("http://api.twitter.com/1/statuses/public_timeline.xml");
    }
    
    public static XmlDocument GetResponse(string uri)
    {
        WebRequest req = WebRequest.Create(new Uri(uri));
    
        XmlDocument doc = new XmlDocument();
        doc.Load(req.GetResponse().GetResponseStream());
        return doc;
    }
    ' VB.NET Code
    
    Sub Main()
        GetResponse("http://api.twitter.com/1/statuses/public_timeline.xml")
    End Sub
    
    Public Function GetResponse(ByVal uri As String) As XmlDocument
    
        Dim req As WebRequest = WebRequest.Create(New Uri(uri))
    
        Dim doc As New XmlDocument()
        doc.Load(req.GetResponse().GetResponseStream())
    
        Return doc
    End Function

    We have used the System.Xml.WebRequest class to create the request and to get the response (as an instance of System.Xml.WebResponse class) from the server. Once we get the XmlDocument, we can walk through the data and retrieve it.

    Authentication

    You can take one of two approaches to authenticate Twitter users:

    • OAuth Authentication:
      An authentication protocol that allows users to approve application to act on their behalf without sharing their password. As this function requires more overhead and requires your application to be registered in the Twitter clients’ directory, we would better use the second approach in our examples.
    • Basic Authentication:
      To provide authentication information in each request you make to the server. Unfortunately, Twitter announced that this method will not be available later.

    Considering a method like statuses/update method that updates the status information of the user (i.e. sends a tweet) we would develop our previous code to be like this:

    // C# Code
    
    public static void Main()
    {
        GetResponse("http://api.twitter.com/1/statuses/update.xml?status=hello%20from%20the%20API",
            "elsheimy", "b@zzword", true);
    }
    
    public static XmlDocument GetResponse(string uri, string username, string password, bool post)
    {
        WebRequest req = WebRequest.Create(new Uri(uri));
        if (post)
            req.Method = "POST";
        if ((username != null) && (username.Trim() != String.Empty) && (!String.IsNullOrEmpty(password)))
            req.Credentials = new NetworkCredential(username.Trim(), password);
    
        XmlDocument doc = new XmlDocument();
        doc.Load(req.GetResponse().GetResponseStream());
        return doc;
    }
    ' VB.NET Code
    
    Sub Main()
        GetResponse("http://api.twitter.com/1/statuses/update.xml?status=hello%20from%20the%20API", "elsheimy", "b@zzword", True)
    End Sub
    
    Public Function GetResponse(ByVal uri As String, ByVal username As String, ByVal password As String, ByVal post As Boolean) As XmlDocument
        Dim req As WebRequest = WebRequest.Create(New Uri(uri))
        If (post) Then
            req.Method = "POST"
        End If
        If ((username  Nothing) And (username.Trim()  String.Empty) And (Not String.IsNullOrEmpty(password))) Then
            req.Credentials = New NetworkCredential(username.Trim(), password)
        End If
    
        Dim doc As XmlDocument = New XmlDocument()
        doc.Load(req.GetResponse().GetResponseStream())
    
        Return doc
    End Function

    Notice how we set the HTTP method based on the function requirements. It is worth mentioning that a status should not exceed 140 UTF-8-encoded characters.

    Encoding URIs

    Have you noticed the previous code? It tries to post the update ‘hello from the API€. Because the text is included with the URI, special handling to the text should be carried. This special handling for text included in URIs is usually called Percent-encoding or URL Encoding. This encoding replaces unsafe characters with their hexadecimal values preceded by percentage (%) signs. Unsafe characters are those somewhat conflicted with URI special characters. For example, if we would encode the text ‘hello from the API€ we would end up with ‘hello%20from%20the%20API€.

    There are many unsafe characters that should be percent-encoded including $, +, &, :, and =. A nice discussion of URL Encoding can be found in the article URL Encoding by Brian Wilson.

    Once we get the idea, we can create our percent-encoding class that encodes/decodes strings:

    // C# Code
    
    private static string[,] _chars = new string[,]
            {
            { "%", "%25" },     // this is the first one
            { "$" , "%24" },
            { "&", "%26" },
            { "+", "%2B" },
            { ",", "%2C" },
            { "/", "%2F" },
            { ":", "%3A" },
            { ";", "%3B" },
            { "=", "%3D" },
            { "?", "%3F" },
            { "@", "%40" },
            { " ", "%20" },
            { """ , "%22" },
            { "", "%3E" },
            { "#", "%23" },
            { "{", "%7B" },
            { "}", "%7D" },
            { "|", "%7C" },
            { "\", "%5C" },
            { "^", "%5E" },
            { "~", "%7E" },
            { "[", "%5B" },
            { "]", "%5D" },
            { "`", "%60" } };
    
    public static string EncodeUrl(string url)
    {
        for (int i = 0; i < _chars.GetUpperBound(0); i++)
            url = url.Replace(_chars[i, 0], _chars[i, 1]);
    
        return url;
    }
    
    public static string DecodeUrl(string url)
    {
        for (int i = 0; i < _chars.GetUpperBound(0); i++)
            url = url.Replace(_chars[i, 1], _chars[i, 0]);
    
        return url;
    }

    ' VB.NET Code
    Public Module UrlEncoder

    Private _chars(,) As String = _
    { _
    {"%", "%25"}, _
    {"$", "%24"}, _
    {"&", "%26"}, _
    {"+", "%2B"}, _
    {",", "%2C"}, _
    {"/", "%2F"}, _
    {":", "%3A"}, _
    {";", "%3B"}, _
    {"=", "%3D"}, _
    {"?", "%3F"}, _
    {"@", "%40"}, _
    {" ", "%20"}, _
    {"", "%22"}, _
    {"”, “%3E”}, _
    {“#”, “%23”}, _
    {“{“, “%7B”}, _
    {“}”, “%7D”}, _
    {“|”, “%7C”}, _
    {“”, “%5C”}, _
    {“^”, “%5E”}, _
    {“~”, “%7E”}, _
    {“[“, “%5B”}, _
    {“]”, “%5D”}, _
    {“‘”, “%60”}}

    Public Function EncodeUrl(ByVal url As String) As String
    For i As Integer = 0 To _chars.GetUpperBound(0) – 1
    url = url.Replace(_chars(i, 0), _chars(i, 1))
    Next

    Return url
    End Function

    Public Function DecodeUrl(ByVal url As String) As String
    For i As Integer = 0 To _chars.GetUpperBound(0) – 1
    url = url.Replace(_chars(i, 1), _chars(i, 0))
    Next

    Return url
    End Function

    End Module

    For clearness, we have included the encoded string of each character along with the character itself. You don’t have to do this. You can convert the character to a number and just output the number in hex format.

    Now we could change the code that updates the status to the following:

    // C# Code
    
    public static void Main()
    {
        string uri;
        string text = UrlEncoder.EncodeUrl("hello from the API");
        uri = "http://api.twitter.com/1/statuses/update.xml?status=" + text;
        GetResponse(uri, "elsheimy", "b@zzwrd", true);
    }
    ' VB.NET Code
    
    Public Sub Main()
    
        Dim uri As String
        Dim text As String = UrlEncoder.EncodeUrl("hello from the API")
        uri = "http://api.twitter.com/1/statuses/update.xml?status=" & text
        GetResponse(uri, "elsheimy", "b@zzwrd", True)
    End Sub

    .NET includes a nice function that escapes (encodes) a URI, System.Uri.EscapeUriString() function. However, this function does not encode all unsafe characters.

    Business Objects

    Once you know the structure of the XML data returned, you can create your business objects that would encapsulate this data. The following are the three classes that would represent our three core objects, the user, the status, and the message.

    // C# Code
    
    public structure TwitterUser
    {
        public long ID;
        public string Name;
        public string ScreenName;
        public string Location;
        public string Description;
        public string ProfileImage;
        public string Url;
        public bool IsProtected;
        public long FollowersCount;
        public long FriendsCount;
        public string CreatedAt;
        public long FavoritesCount;
        public bool Verified;
        public bool Following;
        public long StatusCount;
    }
    
    public structure TwitterStatus
    {
        public string CreatedAt;
        public long ID;
        public string Text;
        public string Source;
        public bool Truncated;
        public long InReplyToStatusID;
        public long InReplyToUserID;
        public bool Favorited;
        public string InReplyToScreenName;
        public TwitterUser User;
    }
    
    public structure TwitterMessage
    {
        public long ID;
        public long SenderID;
        public long SenderScreenName;
        public long RecipientID;
        public long RecipientScreenName;
        public string Text;
        public string CreatedAt;
        public TwitterUser Sender;
        public TwitterUser Recipient;
    }
    ' VB.NET Code
    
    Public Structure TwitterUser
        Public ID As Long
        Public Name As String
        Public ScreenName As String
        Public Location As String
        Public Description As String
        Public ProfileImage As String
        Public Url As String
        Public IsProtected As Boolean
        Public FollowersCount As Long
        Public FriendsCount As Long
        Public CreatedAt As String
        Public FavoritesCount As Long
        Public Verified As Boolean
        Public Following As Boolean
        Public StatusCount As Long
    End Structure
    
    Public Structure TwitterStatus
        Public CreatedAt As String
        Public ID As Long
        Public Text As String
        Public Source As String
        Public Truncated As Boolean
        Public InReplyToStatusID As Long
        Public InReplyToUserID As Long
        Public Favorited As Boolean
        Public InReplyToScreenName As String
        Public User As TwitterUser
    End Structure
    
    Public Structure TwitterMessage
    
        Public ID As Long
        Public SenderID As Long
        Public SenderScreenName As Long
        Public RecipientID As Long
        Public RecipientScreenName As Long
        Public Text As String
        Public CreatedAt As String
        Public Sender As TwitterUser
        Public Recipient As TwitterUser
    End Structure

    Retrieving Data

    Now you can walk through the XML data and get that data inside your objects. The following code returns a list of statuses from your friends’ timeline.

    // C# Code
    
    public static void Main()
    {
        GetStatuses("elsheimy", "b@zzword");
    }
    public static List GetStatuses(string username, string password)
    {
        XmlNode node = GetResponse("http://api.twitter.com/1/statuses/friends_timeline.xml",
            username, password, true);
    
        List lst = new List(node.ChildNodes.Count);
    
        foreach (XmlNode nd in node.ChildNodes)   // for each status
            lst.Add(HandleStatus(nd));
    
        return lst;
    }
    
    public static TwitterStatus HandleStatus(XmlNode nd)
    {
        // HandleNumber, FormatText, HandleBool
        // are just functions that converts strings
        // to numbers, decoded strings, and bool
        TwitterStatus status = new TwitterStatus(
            nd["created_at"].InnerText,
            HandleNumber(nd["id"]),
            FormatText(nd["text"]),
            FormatText(nd["source"]),
            HandleBool(nd["truncated"]),
            HandleNumber(nd["in_reply_to_status_id"]),
            HandleNumber(nd["in_reply_to_user_id"]),
            HandleBool(nd["favorited"]),
            FormatText(nd["in_reply_to_screen_name"]),
            HandleUser(nd["user"]));
        return status;
    }
    
    public static TwitterUser HandleUser(XmlNode nd)
    {
        // HandleNumber, FormatText, HandleBool
        // are just functions that converts strings
        // to numbers, decoded strings, and bool
        long id = HandleNumber(nd["id"]);
        TwitterUser user;
    
        user = new TwitterUser(
            id,
            FormatText(nd["name"]),
            FormatText(nd["screen_name"]),
            FormatText(nd["location"]),
            FormatText(nd["description"]),
            nd["profile_image_url"].InnerText,
            nd["url"].InnerText,
            HandleBool(nd["protected"]),
            HandleNumber(nd["followers_count"]),
            HandleNumber(nd["friends_count"]),
            nd["created_at"].InnerText,
            HandleNumber(nd["favourites_count"]),
            HandleBool(nd["verified"]),
            HandleBool(nd["following"]),
            HandleNumber(nd["statuses_count"]));
    
        return user;
    }
    ' VB.NET Code
    
    Sub Main()
        GetStatuses("elsheimy", "b@zzword")
    End Sub
    
    Public Function GetStatuses(ByVal username As String, ByVal password As String) As List(Of TwitterStatus)
        Dim node As XmlNode = GetResponse("http://api.twitter.com/1/statuses/friends_timeline.xml", username, password, True)
    
        Dim lst As New List(Of TwitterStatus)(node.ChildNodes.Count)
    
        For Each nd As XmlNode In node.ChildNodes
            lst.Add(HandleStatus(nd))
        Next
    
        Return lst
    End Function
    
    Public Function HandleStatus(ByVal nd As XmlNode) As TwitterStatus
        ' HandleNumber, FormatText, HandleBool
        ' are just functions that converts strings
        ' to numbers, decoded strings, and bool
    
        Dim status As New TwitterStatus( _
                nd("created_at").InnerText, _
                HandleNumber(nd("id")), _
                FormatText(nd("text")), _
                FormatText(nd("source")), _
                HandleBool(nd("truncated")), _
                HandleNumber(nd("in_reply_to_status_id")), _
                HandleNumber(nd("in_reply_to_user_id")), _
                HandleBool(nd("favorited")), _
                FormatText(nd("in_reply_to_screen_name")), _
                HandleUser(nd("user")))
    
        Return status
    End Function
    
    Public Function HandleUser(ByVal nd As XmlNode) As TwitterUser
        ' HandleNumber, FormatText, HandleBool
        ' are just functions that converts strings
        ' to numbers, decoded strings, and bool
        Dim id As Long = HandleNumber(nd("id"))
    
        Dim user As New TwitterUser( _
            id, _
            FormatText(nd("name")), _
            FormatText(nd("screen_name")), _
            FormatText(nd("location")), _
            FormatText(nd("description")), _
            nd("profile_image_url").InnerText, _
            nd("url").InnerText, _
            HandleBool(nd("protected")), _
            HandleNumber(nd("followers_count")), _
            HandleNumber(nd("friends_count")), _
            nd("created_at").InnerText, _
            HandleNumber(nd("favourites_count")), _
            HandleBool(nd("verified")), _
            HandleBool(nd("following")), _
            HandleNumber(nd("statuses_count")))
        Return user
    End Function

    twittoo; Sample Application

    twitto, is our WinForms sample application that utilizes the Twitter API. This is just a very simple application with basic functionalities.

    Snapshots

    The following are snapshots of the application:

    Figure 2 - twitto 0
    Figure 3 - twitto 1
    Figure 4 - twitto 2
    Figure 5 - twitto 3
    Figure 6 - twitto 4
    Figure 7 - twitto 5

    Description

    This application was created using C# and WinForms 2.0 technology; it allows the user to navigate through his friends’ timeline, mentions, direct messages, retweets, and friends, and to update his status, reply to tweets, retweets, and to direct messages. Data is not refreshed automatically, the user have to click the ‘refresh€ button. (You can create your own routine that creates a timer that updates the data automatically.)

    Interface

    As you see, the application uses just the Windows Common Controls all around the application; no 3rd party controls were used.

    To represent a status, message, or a user, the application overuses the System.Windows.Forms.TableLayoutPanel control to represent each status, message, or user. It consists of four columns and two rows. The following figure shows how the control is laid-out.

    Figure 8 - TableLayoutPanel Status Template

    URL Shortening

    twittoo, has a very nice feature, it allows the user to insert a shortened URL into his tweets. For this to work, the application makes use of http://is.gd URL shortening service. The following is the function that utilizes the http://is.gd API:

    // C# Code
    
    public static string Shorten(string url)
    {
        if (!System.Text.RegularExpressions.Regex.IsMatch
            (url, @"(http|ftp|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&:/~+#]*[w-@?^=%&/~+#])?"))
            throw new FormatException("The URL you specificed is not in the current format.");
    
        url = Uri.EscapeUriString(url);
        string reqUri = String.Format(@"http://is.gd/api.php?longurl={0}", url);
    
        WebRequest req = WebRequest.Create(reqUri);
        req.Timeout = 5000;
        using (System.IO.StreamReader reader =
            new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
        {
            return reader.ReadLine();
        }
    }
    ' VB.NET
    
    Public Function Shorten(ByVal url As String) As String
        If (Not System.Text.RegularExpressions.Regex.IsMatch _
            (url, "(http|ftp|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&;:/~+#]*[w-@?^=%&;/~+#])?")) Then
            Throw New FormatException("The URL you specificed is not in the current format.")
        End If
    
        url = Uri.EscapeUriString(url)
        Dim reqUri As String = String.Format("http://is.gd/api.php?longurl={0}", url)
    
        Dim req As WebRequest = WebRequest.Create(reqUri)
        req.Timeout = 5000
    
        Dim reader As New System.IO.StreamReader(req.GetResponse().GetResponseStream())
        url = reader.ReadLine()
        reader.Close()
    
        Return url
    End Function

    Download

    Download twittoo; our sample application