Introduction to Microsoft Silverlight

هذا الموضوع متوفر أيضا باللغة العربية، ومتوفر شرح فيديو أيضا، انظر هنا.

Contents

Contents of this article:

  • Contents
  • Overview
  • What is Silverlight
    • Definition
    • Platform Support
    • Rich Interactive Application
    • RIA Stats
    • Why Silverlight
    • Silverlight vs. Flash
    • Silverlight vs. WPF
    • Rich vs. Reach
    • Showcase
    • Deep Zoom
  • Deep Inside
    • Silverlight and XAML
    • Deployment Process
    • Silverlight Architecture
  • Silverlight 5
  • Tooling
    • Microsoft Visual Studio 2010
    • Microsoft Expression Studio 4
  • What’s Next
  • Demo
  • Summary

 

Overview

In this article we’ll have a brief introduction to Microsoft Silverlight, see how it fits with other technologies today, and watch it in action. Get ready!

 

What is Silverlight

Definition

Silverlight is a Microsoft technology aimed to help developers create rich interactive Web applications with the best user interface features and functionalities. It’s available as a plugin for almost all famous browsers available today, and it’s used to deliver the next generation media and Web applications.

Figure 1 - Silverlight Logo

Figure 1 - Silverlight Logo

When we say rich applications we don’t mean those with amazing interfaces and lots of graphics. Indeed, we mean by “rich” those have lots of functionalities not available for standard Web applications. Common examples of rich applications are online document editors and image processors; both are very interactive and offer lots of functionalities that are usually not available for standard Web applications. And that actually what Silverlight is devoted for, its main goal is to allow for developing rich interactive applications for the Web.

Platform Support

Unlike many other Microsoft technologies, Silverlight applications can run everywhere. It’s said to be cross-platform, cross-browser, and cross-device. It can run on Windows, Linux, and even Mac, it can run on Internet Explorer, Mozilla Firefox, Google Chrome, and many others, and it also can run on PCs, mobile devices, and handhelds. Really it can run everywhere without any code changes!

One more interesting thing is that Silverlight Web applications can be hosted on any server. You can host your Silverlight application on a Windows, Linux, or Mac server without any additional code changes or configuration.

Rich Interactive Applications

We have been talking about rich interactive applications for a while; now let’s see what a rich interactive application really means.

A Rich Interactive/Internet Application (RIA) is a Web application that’s very interactive with the user and has lots of functionalities. It’s very similar to desktop applications comparing interactivity and features; however, it’s a Web application that runs on the browser not the desktop. So we can say that RIA applications have the best functionalities and user interface features of desktop applications and Web applications.

Figure 2 - RIA

Figure 2 - RIA

Today, there’re lots of technologies available for creating RIA applications. The most famous platforms are Adobe Flash, Microsoft Silverlight, and Sun Java. Worth mentioning that every platform of the above mentioned (that includes Silverlight of course) is available through a plugin for the browser, and therefore its runtime must be installed on user’s machine in order to be able to run the application.

RIA Stats

Now someone asks: Who wins the race? What’s the best RIA platform that one can spend his time and effort to learn?

First of all, let’s have a look at the following diagrams that represent penetration rates of Adobe Flash, Microsoft Silverlight, and Sun Java. The first diagram we have comes from http://riastats.com and it shows that Adobe Flash is installed on almost 96% of internet-connected machines. Microsoft Silverlight comes in the second place with about 74% of total internet-connected machines. And Sun Java comes third with about 73% of internet-connected machines.

Figure 3 - RIA Stats

Figure 3 - RIA Stats

StatOWL shows a bit different data with more details:

Figure 4 - Stats from StatOWL

Figure 4 - Stats from StatOWL

Looking at the above diagrams we can see that Microsoft Silverlight did a great job in a very short time (first release was on 2007.) However, we can’t depend much on this data since, as you know, Microsoft Silverlight is installed automatically on Windows machines via Windows Update.

Now, let’s have a look at Microsoft Silverlight features and see what makes it the best RIA platform yet.

Why Silverlight

Other than being delivered by Microsoft, some features of Silverlight are:

  • It’s FREE.
  • It runs on all popular browsers, platforms, and devices.
  • It can be run in browser and as a desktop application.
  • Easy to create excellent UIs that looks “WOW”.
  • Enables business application development.
  • Supports 2D/3D animations/graphics.
  • Natively supports CLR and .NET Framework.
  • Can be automated using JavaScript.
  • Supports a variety of media (audio/video) formats with streaming capabilities.
  • Supports a variety of rich controls including the DataGrid.
  • Supports a variety of enterprise technologies including WCF.

In addition, Silverlight is considered to be the main development framework for Windows Phone.

Figure 5 - Windows Phone

Figure 5 - Windows Phone

Silverlight vs. Flash

Silverlight and Flash are very similar, so which is better, Silverlight or Flash? Since I’m a Microsoft developer and since you are reading now in a .NET blog, and although I haven’t ever developed for Flash, I can say that Silverlight is the best RIA platform ever!!! However, we need to be more serious.

InfoWorld did a review and compared between Silverlight and Flash, and the results were so great, Silverlight passed Flash and scored 8.3 points, while Flash got 7.8 points only.

Figure 6 - Silverlight vs. Flash, InfoWorld

Figure 6 - Silverlight vs. Flash, InfoWorld

Silverlight vs. WPF

Windows Presentation Foundation (WPF) is a graphical subsystem utilizing DirectX for rendering UI in Windows-based application, developed by Microsoft and introduced as part of Microsoft .NET Framework 3.0 and Windows Vista. WPF is considered to be the replacement for WinForms (that considered now Feature-Complete,) while WinForms relies on the older GDI subsystem, WPF relies on DirectX.

On the other hand, Silverlight is actually a subset of WPF, and formerly Silverlight was codenamed WPF/E (WPF/Everywhere) because it’s considered to be the cross-platform version of WPF. And while WPF focuses on desktop development, Silverlight focuses on Web development.

Figure 7 - Silverlight vs. WPF

Figure 7 - Silverlight vs. WPF

Rich vs. Reach

The following diagram compares some of the available Web development technologies in terms of richness (i.e. UI functionalities) and reach (platform and browser support.)

Figure 8 - Rich vs. Reach

Figure 8 - Rich vs. Reach

From the above diagram we can see that WPF has the best UI features today. However, it’s devoted primarily for desktop development, and it can run only on Windows platforms.

On the other hand, ASP.NET can run everywhere, but unfortunately it doesn’t support the UI functionalities required for today’s Web.

And finally, Silverlight has the best of UI functionalities, and it also supports a wide range of platforms and browsers (its platform/browser support is expanded each release.)

Showcase

To get a solid understanding of what Silverlight can do, check out some of the Silverlight applications from around the world:

And one of the most impressive applications is SilveOs (http://silveos.com/); a mini-operating system for the Web.

And thousands of Silverlight applications are available here too:  http://www.silverlight.net/showcase.

Deep Zoom

And another great feature of Silverlight is the DeepZoom technology that was introduced by Microsoft as part of Silverlight. DeepZoom allows you to view very large high resolution images. It reduces the time of initial load by downloading only the region being viewed at the resolution it’s displayed at. Subsequent regions are downloaded as the user pans to (or zooms into) them.

Figure 9 - Deep Zoom, Microsoft Silverlight

Figure 9 - Deep Zoom, Microsoft Silverlight

 

Deep Inside

Silverlight and XAML

Like WPF, user interface in Silverlight is declared in a specific language called Extensible Markup Language (or XAML, pronounced ‘Zammel’.) XAML is an XML-based language created by Microsoft which is used to initialize structured values and objects. XAML elements are mapped directly to CLR objects (e.g. a <Button> element maps to a Button object.)

Figure 10 - XAML Logo

Figure 10 - XAML Logo

Former ASP.NET developers are somewhat familiar with the nature of XAML. You have a WYSIWYG XAML designer that you use to design the interface of your application. The code for this interface is available through a code-behind file, where you can write in your preferred .NET language.

The concept of two files for the same page (e.g. a XAML file for the interface and a CS file for the C# code) separates two main roles in application development, design and development. The designer can work in the XAML file, and the developer can work in the code file, and both files are linked together. This also leads to a loosely-coupled design that separates user interface code from the business logic.

Figure 11 - Designer vs. Developer

Figure 11 - Designer vs. Developer

Deployment Process

What steps you would follow to deploy your Silverlight application to your users? That’s what this section is devoted for.

When you build your Silverlight application, the XAML markup, as well as the code and all other resources, is compiled into .NET assemblies which are then compressed using ZIP and stored in a XAP (.xap) file.

Figure 12 - XAP Files

Figure 12 - XAP Files

The XAP file can then be hosted in a Web server and referenced by Web pages declaring the Silverlight plugin object. And when the user navigates to the page, the XAP file is downloaded to his PC and executed on the Web page by the Silverlight runtime.

Figure 13 - Silverlight Application Deployment Process

Figure 13 - Silverlight Application Deployment Process

So all you need is just to develop your application, get the XAP file, insert the plugin into a Web page, and then publish the page and the XAP file to the Web.

Silverlight Architecture

The following illustration shows the essential architecture and components of Microsoft Silverlight. It shows how the presentation (interface) core components fit together with other .NET and Silverlight components, and what services does the provider offer.

Figure 14 - Silverlight Architecture

Figure 14 - Silverlight Architecture

 

Silverlight 5

The current stable version of Silverlight is Silverlight 4. Back to PDC 2010 the 5th version of Silverlight was introduced, it’s still in Beta but it’s supposed to be released soon.

Figure 15 - Silverlight 5 Logo

Figure 15 - Silverlight 5 Logo

Here’s a brief overview of the forthcoming Silverlight 5 features:

  • Media:
    • Hardware Video Decode
    • Better Power Management
    • Remote Control Support
  • Text and Printing:
    • Better Text Rendering
    • Full OpenType Support
  • Graphics:
    • GPU Accelerated Graphics
    • 3D Graphics Support
  • XAML:
    • XAML Debugging
  • Application Development:
    • Windows Azure Support
    • P/Invoke
  • Testing and Performance:
    • Automated UI Testing
    • Faster Startup
    • Hardware Acceleration
    • 64-bit Support

More about Silverlight 5 can be found here: http://www.microsoft.com/silverlight/future.

 

Tooling

The most common tools for Silverlight are Microsoft Visual Studio 2010 and Microsoft Expression Studio 4.

Microsoft Visual Studio 2010

Best for developers, good for designers. Check it out here: http://www.microsoft.com/visualstudio/en-us.

Figure 16 - Microsoft Visual Studio 2010

Figure 16 - Microsoft Visual Studio 2010

Microsoft Expression Studio 4

Consists of a 5 tools:

  • Microsoft Expression Blend
    Visual user interface builder for Silverlight and WPF.
  • Microsoft Expression Web
    WYSIWYG website designer and editor.
  • Microsoft Expression Design
    Raster and vector graphics editor.
  • Microsoft Expression Media
    Digital asset and media manager.
  • Microsoft Expression Encoder
    Profession media (video/audio) encoder
Figure 17 - Microsoft Expression Studio 4

Figure 17 - Microsoft Expression Studio 4

 

What’s Next

To start with Silverlight, you have to install the following components:

 

Demo

In the following example, we’ll create the Hello World application in Silverlight. Follow those steps:

First, ensure that Silverlight SDK is installed on your PC, and launch Visual Studio 2010 and select New Project.

Figure 18 - Creating a New Silverlight Application

Figure 18 - Creating a New Silverlight Application

From the New Project dialog, select your desired language from the left and select Silverlight as project type. From the middle pane, select Silverlight Application to start.

Now another dialog appears asks you to specify whether to create another Web application to host the Silverlight application or not. As you know, Silverlight applications run inside a plugin defined in a Web page, and that dialog asks if to create a new Web Application project for you to host the Silverlight application or to create just a simple HTML page to host it. Leave the dialog with no changes and ensure that you have selected Silverlight 4 from the Silverlight Version combo box and click OK to proceed.

Figure 19 - New Silverlight Application Settings

Figure 19 - New Silverlight Application Settings

Now let’s have a look at what Visual Studio has created for us. Looking at the Solution Explorer we can see that Visual Studio has created two projects, one is the Silverlight project, and the other is a Web project that’s going to host this Silverlight application.

Figure 20 - Silverlight Project in Solution Explorer

Figure 20 - Silverlight Project in Solution Explorer

Looking at the Web project we can see that VS has included two test pages in that project, the first is an ASPX page and the second is a simple HTML page, both define the Silverlight plugin and both are ready to show you your Silverlight application when you browse to them. The difference is that ASPX pages can define ASP.NET elements and code, while the simple static HTML cannot.

Back to the Silverlight application, we can see that it define 4 files:

  1. App.xaml:
    Define application-wide interface elements.
  2. App.xaml.cs (C# code file, linked to App.xaml):
    Define the startup logic and any other application-wide code.
  3. MainPage.xaml:
    The main application page; contains the interface elements.
  4. MainPage.xaml.cs (C# code file, linked to MainPage.cs):
    The business logic and code for the main application page.

Then we have two pages, the first is App.xaml that defines the application-wide elements and code (inside App.xaml.cs,) and the second is MainPage.xaml that defines the main page of your application where you can define your interface elements and code them (inside MainPage.xaml.cs.)

Now let’s design our interface. Go to MainPage.xaml and inside the <Grid> element define a Button (you can also drag the button from the Toolbox to the designer to define it):

<Button Width="100" Height="25" Content="Say Hello" Click="Button_Click" />
Figure 21 - Button in the Page

Figure 21 - Button in the Page

From the previous line of code we can see that we have defined a Button control using a <Button> element, and we have also set the control’s characteristics and properties using the element attributes. And to have our button respond to user clicks, we have wired up the Click event into the function Button_Click() that we’re going to define it in the code file.

Now go to MainPage.xaml.cs and define the Click event handler for the button:

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello, World!");
}
Figure 22 - The Code-Behind File

Figure 22 - The Code-Behind File

Now run the application and try it.

Figure 23 - Running Silverlight Application

Figure 23 - Running Silverlight Application

Before we leave this section, let’s have a look over the plugin required for Silverlight. Go to and of the test pages on the Web project and step down until you reach the <object> element that defines the plugin. Simply, the Silverlight application requires only the following HTML code to define its plugin:

<div id="silverlightControlHost">
  <object data="data:application/x-silverlight-2,"
    type="application/x-silverlight-2" width="100%" height="100%">
      <param name="source" value="ClientBin/SilverlightApplication1.xap"/>
      ...
  </object>
  <iframe id="_sl_historyFrame"
      style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>
</div>

As you see, we have references the XAP file in the page by using the source parameter. When you build your application in Visual Studio, it will create a new folder besides the test page called ClientBin and put the XAP file inside it so you can reference it in the page.

Clear, aih?

 

Summary

  • Silverlight is a cross-platform application framework for writing and running rich Internet applications (RIA.)
  • Its runtime is available as a cross-browser, cross-platform, and cross-device plug-in.
  • It’s the main development framework for Windows Phone.
  • It’s a subset of WPF so it depends on XAML for UI design.
  • You define the interface using XAML, and write the code using your preferred .NET language.
  • The XAML markup, as well as the code, is compiled into .NET assemblies and compressed into a XAP file.
  • The XAP file is then referenced by a prepared Web page and then downloaded to client’s PC when he navigates to the page.
  • Version 4 is the current stable version of Silverlight.
  • Silverlight 5 is currently in beta and it will be released soon.
  • You use Visual Studio 2010 and Microsoft Expression Studio for developing and designing your Silverlight application.
  • Microsoft Expression Studio is preferred for you if you are a designer.

 

Building Applications that Can Talk

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

Overview

Stephen Hawking is one of the most famous people using speech synthesis to communicate

Stephen Hawking is one of the most famous people using speech synthesis to communicate

In this article we are going to explore the Speech API library that’s part of the TTS SDK that helps you reading text and speaking it. We’re going to see how to do it programmatically using C# and VB.NET and how to make use of LINQ to make it more interesting. The last part of this article talks about…… won’t tell you more, let’s see!

Introduction

The Speech API library that we are going to use today is represented by the file sapi.dll which’s located in %windir%System32SpeechCommon. This library is not part of the .NET BCL and it’s not even a .NET library, so we’ll use Interoperability to communicate with it (don’t worry, using Visual Studio it’s just a matter of adding a reference to the application.)

Implementation

In this example, we are going to create a Console application that reads text from the user and speaks it. To complete this example, follow these steps:

As an example, we’ll create a simple application that reads user inputs and speaks it. Follow these steps:

  1. Create a new Console application.
  2. Add a reference to the Microsoft Speech Object Library (see figure 1.)

    Figure 1 - Adding Reference to SpeechLib Library

    Figure 1 - Adding Reference to SpeechLib Library

  3. Write the following code and run your application:
// C#

using SpeechLib;

static void Main()
{
    Console.WriteLine("Enter the text to read:");
    string txt = Console.ReadLine();
    Speak(txt);
}

static void Speak(string text)
{
    SpVoice voice = new SpVoiceClass();
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault);
}
' VB.NET

Imports SpeechLib

Sub Main()
    Console.WriteLine("Enter the text to read:")
    Dim txt As String = Console.ReadLine()
    Speak(txt)
End Sub

Sub Speak(ByVal text As String)
    Dim voice As New SpVoiceClass()
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault)
End Sub

If you are using Visual Studio 2010 and .NET 4.0 and the application failed to run because of Interop problems, try disabling Interop Type Embedding feature from the properties on the reference SpeechLib.dll.

Building Talking Strings

Next, we’ll make small modifications to the code above to provide an easy way to speak a given System.String. We’ll make use of the Extension Methods feature of LINQ to add the Speak() method created earlier to the System.String. Try the following code:

// C#

using SpeechLib;

static void Main()
{
    Console.WriteLine("Enter the text to read:");
    string txt = Console.ReadLine();
    txt.Speak();
}

static void Speak(this string text)
{
    SpVoice voice = new SpVoiceClass();
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault);
}
' VB.NET

Imports SpeechLib
Imports System.Runtime.CompilerServices

Sub Main()
    Console.WriteLine("Enter the text to read:")
    Dim txt As String = Console.ReadLine()
    txt.Speak()
End Sub

<Extension()> _
Sub Speak(ByVal text As String)
    Dim voice As New SpVoiceClass()
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault)
End Sub

I Love YOU ♥

Let’s make it more interesting. We are going to code a VBScript file that says “I Love YOU” when you call it. To complete this example, these steps:

  1. Open Notepad.
  2. Write the following code:
    CreateObject("SAPI.SpVoice").Speak "I love YOU!"

    Of course, CreateObject() is used to create a new instance of an object resides in a given library. SAPI is the name of the Speech API library stored in Windows Registry. SpVoice is the class name.

  3. Save the file as ‘love.vbs’ (you can use any name you like, just preserve the vbs extension.)
  4. Now open the file and listen, who is telling that he loves you!

Microsoft Speech API has many voices; two of them are Microsoft Sam (male), the default for Windows XP and Windows 2000, and Microsoft Ann (female), the default for Windows Vista and Windows 7. Read more about Microsoft TTS voices here.

Thanks to our friend, Mohamed Gafar, for providing the VBScript.

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.

.NET Interoperability at a Glance 3 – Unmanaged Code Interoperation

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

See more Interoperability examples here.

Contents

Contents of this article:

  • Contents
  • Read also
  • Overview
  • Unmanaged Code Interop
  • Interop with Native Libraries
  • Interop with COM Components
  • Interop with ActiveX Controls
  • Summary
  • Where to go next

Read also

More from this series:

Overview

This is the last article in this series, it talks about unmanaged code interoperation; that’s, interop between .NET code and other code from other technologies (like Windows API, native libraries, COM, ActiveX, etc.)

Be prepared!

Introduction

Managed code interop wasn’t so interesting, so it’s the time for some fun. You might want to call some Win32 API functions, or it might be interesting if you make use of old, but useful, COM components. Let’s start!

Unmanaged Code Interop

Managed code interoperation isn’t so interesting, but this is. Unmanaged interoperation is not easy as the managed interop, and it’s also much difficult and much harder to implement. In unmanaged code interoperation, the first system is the .NET code; the other system might be any other technology including Win32 API, COM, ActiveX, etc. Simply, unmanaged interop can be seen in three major forms:

  1. Interoperation with Native Libraries.
  2. Interoperation with COM components.
  3. Interoperation with ActiveX.

Interop with Native Libraries

This is the most famous form of .NET interop with unmanaged code. We usually call this technique, Platform Invocation, or simply PInvoke. Platform Invocation or PInvoke refers to the technique used to call functions of native unmanaged libraries such as the Windows API.

To PInvoke a function, you must declare it in your .NET code. That declaration is called the Managed Signature. To complete the managed signature, you need to know the following information about the function:

  1. The library file which the function resides in.
  2. Function name.
  3. Return type of the function.
  4. Input parameters.
  5. Other relevant information such as encoding.

Here comes a question, how could we handle types in unmanaged code that aren’t available in .NET (e.g. BOOL, LPCTSTR, etc.)?

The solution is in Marshaling. Marshaling is the process of converting unmanaged types into managed and vice versa (see figure 1.) That conversion can be done in many ways based on the type to be converted. For example, BOOL can simply be converted to System.Boolean, and LPCTSTR can be converted to System.String, System.Text.StringBuilder, or even System.Char[]. Compound types (like structures and unions) are usually don’t have counterparts in .NET code and thus you need to create them manually. Read our book about marshaling here.

Figure 1 - The Marshaling Process
Figure 1 – The Marshaling Process

To understand P/Invoke very well, we’ll take an example. The following code switches between mouse button functions, making the right button acts as the primary key, while making the left button acts as the secondary key.

In this code, we’ll use the SwapMouseButtons() function of the Win32 API which resides in user32.dll library and has the following declaration:

BOOL SwapMouseButton(
    BOOL fSwap
    );

Of course, the first thing is to create the managed signature (the PInvoke method) of the function in .NET:

// C#
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SwapMouseButton(bool fSwap);
' VB.NET
Declare Auto Function SwapMouseButton Lib "user32.dll" _
    (ByVal fSwap As Boolean) As Boolean

Then we can call it:

// C#

public void MakeRightButtonPrimary()
{
    SwapMouseButton(true);
}

public void MakeLeftButtonPrimary()
{
    SwapMouseButton(false);
}
' VB.NET

Public Sub MakeRightButtonPrimary()
    SwapMouseButton(True)
End Sub

Public Sub MakeLeftButtonPrimary()
    SwapMouseButton(False)
End Sub

Interop with COM Components

The other form of unmanaged interoperation is the COM Interop. COM Interop is very large and much harder than P/Invoke and it has many ways to implement. For the sake of our discussion (this is just a sneak look at the technique,) we’ll take a very simple example.

COM Interop includes all COM-related technologies such as OLE, COM+, ActiveX, etc.

Of course, you can’t talk directly to unmanaged code. As you’ve seen in Platform Invocation, you have to declare your functions and types in your .NET code. How can you do this? Actually, Visual Studio helps you almost with everything so that you simply to include a COM-component in your .NET application, you go to the COM tab of the Add Reference dialog (figure 2) and select the COM component that you wish to add to your project, and you’re ready to use it!

Figure 2 - Adding Reference to SpeechLib Library
Figure 2 – Adding Reference to SpeechLib Library

When you add a COM-component to your .NET application, Visual Studio automatically declares all functions and types in that library for you. How? It creates a Proxy library (i.e. assembly) that contains the managed signatures of the unmanaged types and functions of the COM component and adds it to your .NET application.

The proxy acts as an intermediary layer between your .NET assembly and the COM-component. Therefore, your code actually calls the managed signatures in the proxy library that forwards your calls to the COM-component and returns back the results.

Keep in mind that proxy libraries also called Primary Interop Assemblies (PIAs) and Runtime Callable Wrappers (RCWs.)

Best mentioning that Visual Studio 2010 (or technically, .NET 4.0) has lots of improved features for interop. For example, now you don’t have to ship a proxy/PIA/RCW assembly along with your executable since the information in this assembly can now be embedded into your executable; this is what called, Interop Type Embedding.

Of course, you can create your managed signatures manually, however, it’s not recommended especially if you don’t have enough knowledge of the underlying technology and the marshaling of functions and types (you know what’s being said about COM!)

As an example, we’ll create a simple application that reads user inputs and speaks it. Follow these steps:

  1. Create a new Console application.
  2. Add a reference to the Microsoft Speech Object Library (see figure 2.)
  3. Write the following code and run your application:
// C#

using SpeechLib;

static void Main()
{
    Console.WriteLine("Enter the text to read:");
    string txt = Console.ReadLine();
    Speak(txt);
}

static void Speak(string text)
{
    SpVoice voice = new SpVoiceClass();
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault);
}
' VB.NET

Imports SpeechLib

Sub Main()
    Console.WriteLine("Enter the text to read:")
    Dim txt As String = Console.ReadLine()
    Speak(txt)
End Sub

Sub Speak(ByVal text As String)
    Dim voice As New SpVoiceClass()
    voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault)
End Sub

If you are using Visual Studio 2010 and .NET 4.0 and the application failed to run because of Interop problems, try disabling Interop Type Embedding feature from the properties on the reference SpeechLib.dll.

Interop with ActiveX Controls

ActiveX is no more than a COM component that has an interface. Therefore, nearly all what we have said about COM components in the last section can be applied here except the way we add ActiveX components to our .NET applications.

To add an ActiveX control to your .NET application, you can right-click the Toolbox, select Choose Toolbox Items, switch to the COM Components tab and select the controls that you wish to use in your application (see figure 3.)

Figure 3 - Adding WMP Control to the Toolbox
Figure 3 – Adding WMP Control to the Toolbox

Another way is to use the aximp.exe tool provided by the .NET Framework (located in Program FilesMicrosoft SDKsWindowsv7.0Abin) to create the proxy assembly for the ActiveX component:

aximp.exe "C:WindowsSystem32wmp.dll"

Not surprisingly, you can create the proxy using the way for COM components discussed in the previous section, however, you won’t see any control that can be added to your form! That way creates control class wrappers for unmanaged ActiveX controls in that component.

Summary

So, unmanaged code interoperation comes in two forms: 1) PInvoke: interop with native libraries including the Windows API 2) COM-interop which includes all COM-related technologies like COM+, OLE, and ActiveX.

To PInvoke a method, you must declare it in your .NET code. The declaration must include 1) the library which the function resides in 2) the return type of the function 3) function arguments.

COM-interop also need function and type declaration and that’s usually done for you by the Visual Studio which creates a proxy (also called RCW and PIA) assembly that contains managed definitions of the unmanaged functions and types and adds it to your project.

Where to go next

Read more about Interoperability here.

More from this series:

.NET Interoperability at a Glance 2 – Managed Code Interoperation

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

See more Interoperability examples here.

Contents

Contents of this article:

  • Contents
  • Read also
  • Overview
  • Introduction
  • Forms of Interop
  • Managed Code Interop
  • Summary
  • Where to go next

Read also

More from this series:

Overview

In the previous article, you learnt what interoperability is and how it relates to the .NET Framework. In this article, we’re going to talk about the first form of interoperability, the Managed Code Interop. In the next article, we’ll talk about the other forms.

Introduction

So, to understand Interoperation well in the .NET Framework, you must see it in action. In this article, we’ll talk about the first form of .NET interoperability and see how to implement it using the available tools.

Just a reminder, Interoperability is the process of communication between two separate systems. In .NET Interop, the first system is always the .NET Framework; the other system might be any other technology.

Forms of Interop

Interoperability in .NET Framework has two forms:

  • Managed Code Interoperability
  • Unmanaged Code Interoperability

Next, we have a short discussion of each of the forms.

Managed Code Interop

This was one of the main goals of .NET Framework. Managed Code Interoperability means that you can easily communicate with any other .NET assembly no matter what language used to build that assembly.

Not surprisingly, because of the nature of .NET Framework and its runtime engine (the CLR,) .NET code supposed to be called Managed Code, while any other code is  unmanaged.

To see this in action, let’s try this:

  1. Create a new Console application in the language you like (C#/VB.NET.)
  2. Add a new Class Library project to the solution and choose another language other than the one used in the first project.
  3. In the Class Library project, add the following code (choose the suitable project):
    // C#
    
    public static class Hello
    {
        public static string SayHello(string name)
        {
            return "Hello, " + name;
        }
    }
    ' VB.NET
    
    Public Module Hello
        Public Function SayHello(ByVal name As String) As String
            Return "Hello, " & name
        End Function
    End Module
  4. Now, go back to the Console application. Our goal is to call the function we have added to the other project. To do this, you must first add a reference to the library in the first project. Right-click the Console project in Solution Explorer and choose Add Reference to open the Add Reference dialog (figure 1.) Go to the Projects tab and select the class library project to add it.

    Figure 1 - Add Reference to a friend project

    Figure 1 - Add Reference to a friend project

  5. Now you can add the following code to the Console application to call the SayHello() function of the class library.
    // C#
    
    static void Main()
    {
        Console.WriteLine(ClassLibrary1.Hello.SayHello("Mohammad Elsheimy"));
    }
    ' VB.NET
    
    Sub Main()
        Console.WriteLine(ClassLibrary1.Hello.SayHello("Mohammad Elsheimy"))
    End Sub

How this happened? How could we use the VB.NET module in C# which is not available there (or the C#’s static class in VB which is not available there too)?

Not just that, but you can inherit C# classes from VB.NET (and vice versa) and do all you like as if both were created using the same language. The secret behind this is the Common Intermediate Language (CIL.)

When you compile your project, the compiler actually doesn’t convert your C#/VB.NET code to instructions in the Machine language. Rather, it converts your code to another language of the .NET Framework, which is the Common Intermediate Language. The Common Intermediate Language, or simply CIL, is the main language of .NET Framework which inherits all the functionalities of the framework, and which all other .NET languages when compiled are converted to it.

So, the CIL fits as a middle layer between your .NET language and the machine language. When you compile your project, the compiler converts your code to CIL statements and emits them in assembly file. In runtime, the compiler reads the CIL from the assembly and converts them to machine-readable statements.

How CIL helps in interoperation? The communication between .NET assemblies is now done through the CIL of the assemblies. Therefore, you don’t need to be aware of structures and statements that are not available in your language since every statement for any .NET language has a counterpart in IL. For example, both the C# static class and VB.NET module convert to CIL static abstract class (see figure 2.)

Figure 2 - CIL and other .NET languages

Figure 2 - CIL and other .NET languages

Managed Interop is not restricted to C# and VB.NET only; it’s about all languages run inside the CLR (i.e. based on .NET Framework.)

If we have a sneak look at the CIL generated from the Hello class which is nearly the same from both VB.NET and C#, we would see the following code:

.class public abstract auto ansi sealed beforefieldinit ClassLibrary1.Hello
       extends [mscorlib]System.Object
{

    .method public hidebysig static string  SayHello(string name) cil managed
    {
      // Code size       12 (0xc)
      .maxstack  8
      IL_0000:  ldstr      "Hello, "
      IL_0005:  ldarg.0
      IL_0006:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
      IL_000b:  ret
    } // end of method Hello::SayHello

} // end of class ClassLibrary1.Hello

On the other hand, this is the code generated from the Main function (which is also the same from VB.NET/C#):

.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.Program
       extends [mscorlib]System.Object
{

    .method private hidebysig static void  Main() cil managed
    {
      .entrypoint
      .maxstack  8
      IL_0000:  ldstr      "Mohammad Elsheimy"
      IL_0005:  call       string [ClassLibrary1]ClassLibrary1.Hello::SayHello(string)
      IL_000a:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_000f:  ret
    } // end of method Program::Main

} // end of class ConsoleApplication1.Program

You can use the ILDasm.exe tool to get the CIL code of an assembly. This tool is located in Program FilesMicrosoft SDKsWindows<version>bin.

Here comes a question, is there CIL developers? Could we write the CIL directly and build it into .NET assembly? Why we can’t find much (if not any) CIL developers? You can extract the answer from the CIL code itself. As you see, CIL is not so friendly and its statements are not so clear. Plus, if we could use common languages to generate the CIL, we we’d like to program in CIL directly? So it’s better to leave the CIL for the compiler.

Now, let’s see the other form of .NET interoperation, Unmanaged Code Interoperability.

Summary

So, the secret of Managed Code Interoperation falls in the Common Intermediate Language or CIL. When you compile your code, the compiler converts your C#/VB.NET (or any other .NET language) to CIL instructions and saves them in the assembly, and that’s the secret. The linking between .NET assemblies of different languages relies on the fact that the linking is actually done between CILs of the assemblies. The assembly code doesn’t (usually) have any clue about the language used to develop it. In the runtime, the compiler reads those instructions and converts them to machine instructions and execute them.

Next, we’ll talk about the other form of .NET Interoperation, it’s the interoperation with unmanaged code.

Where to go next

Read more about Interoperability here.

More from this series:

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.

Understanding Value Types and Reference Types

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

Contents

Contents of this article:

  • Contents
  • Introduction
  • Passing Mechanism
  • The Two Genres
  • Value Types
  • Reference Types
  • Boxing and Unboxing
    • Manual Boxing
    • Manual Unboxing
    • Automatic Boxing
    • Automatic Unboxing
  • Summary

Introduction

Today, we’ll have a brief discussion of value types and reference types in .NET framework and how their behavior change while used or passed to functions. We’ll talk about the passing mechanism, the two genres of .NET types, the scope, and the conversion routines between the two genres.

Passing Mechanism

When you pass an object to a function, this object can be passed either by value or by reference.

To pass an object by value means that a copy of the object is passed to the function not the object itself so changes to the object inside the function won’t affect your original copy.

On the other hand, passing an object by reference means passing that object itself so changes to the object inside that function is reflected on your original copy.

Consider the following example. Although the function changed the value of i, the change didn’t affect the original variable that’s because the variable is passed by value.

// C#

static void Main()
{
    int i = 10;
    int j = i;

    j = 5;

    // you expect '5'
    Console.WriteLine(i);
    // but i is still 10 !!

    // Now you try another way

    Sqr(i);

    // you expect '100'
    Console.WriteLine(i);
    // but i is still 10 !!!
}

static void Sqr(int i)
{
    i *= i;
}
' VB.NET

Sub Main()
    Dim i As Integer = 10
    Dim j As Integer = i

    j = 5

    ' you expect '5'
    Console.WriteLine(i)
    ' but i is still 10 !!!

    ' now you try another way

    Sqr(i)

    ' you expect '100'
    Console.WriteLine(i)
    ' but i is still 10 !!!
End Sub

Sub Sqr(ByVal i As Integer)
    i = i * i
End Sub

Now, let’s try something else. The following example passes i by reference.

// C#

static void Main()
{
    int i = 10;

    Sqr(ref i);

    // you expect '100'
    Console.WriteLine(i);

    // you are right!
}

static void Sqr(ref int i)
{
    i *= i;
}
' VB.NET

Sub Main()
    Dim i As Integer = 10

    Sqr(i)

    ' you expect '100'
    Console.WriteLine(i)

    ' you are right!
End Sub

Sub Sqr(ByRef i As Integer)
    i = i * i
End Sub

Notice how the ref keyword in C# (ByRef in VB.NET) changed the overall behavior. Now, i itself is passed to our function, so the changes made in the function affected the original variable (both are the same.)

The Two Genres

Talking about passing object by value or by reference leads up to talk about the two major genres of types in .NET Framework:

  • Value Types
  • Reference Types

Value Types

Value types are those normally passed by value unless you explicitly specify the ref keyword (or ByVal in VB.NET) to override the default behavior and pass the object by reference.

Value types in .NET are those inherit -directly or indirectly- from System.ValueType including all structures, enumerations, and primitives (integers, floats, etc.)

The previous examples use an integer value that’s absolutely a value-type.

Value types are stored on the first section of the memory, the stack. Thus, they are removed from memory as soon as their scope ends. The scope marks the beginning and the end of object’s life (object is considered alive at the time you declare it.) See the following code the marks scopes inside a class.

// C#

class ClassScope
{
    // Scope 1

    void Method1()
    {
        // Scope 1.1

        {
            // Scope 1.1.1
            {
                // Scope 1.1.1.1
            }

            {
                // Scope 1.1.1.2
            }
        }
    }

    void Method2()
    {
        // Scope 1.2

        if (true)
        {
            // Scope 1.2.1

            while (true)
            {
                // Scope 1.2.1.1
            }
        }
    }
}
' VB.NET

Class ClassScope
    ' Scope 1

    Sub Method1()
        ' Scope 1.1
    End Sub

    Sub Method2()
        ' Scope 1.2

        If True Then
            ' Scope 1.2.1

            Do While True
                ' Scope 1.2.1.1
            Loop
        End If
    End Sub
End Class

Reference Types

Reference types are those normally passed by reference and never can be passed by value. Reference types include all objects other than value types, we mean all other classes inherit from System.Object -directly or indirectly- and don’t inherit from System.ValueType.

Reference types are stored in the other version of the memory, the heap, and you can’t determine when the object is removed from memory since the heap is fully managed by the memory manager of .NET, the GC (Garbage Collector.)

Now, let’s see the difference between value types and reference types in action. The following example instantiates two objects, one is a structure (value type) and the other is a class (reference types.) After that, both objects are passed to two functions, both try to change the contents of the objects. The changes of the function affect the reference type outside, while the other value type object outside the function doesn’t get affected.

// C#

static void Main()
{
    ValStruct valObj = new ValStruct();
    RefClass refObj = new RefClass();

    valObj.x = 4;
    valObj.y = 4;
    refObj.x = 4;
    refObj.y = 4;

    MultipleStruct(valObj);
    MultipleClass(refObj);

    Console.WriteLine("Struct:tx = {0},ty = {1}",
        valObj.x, valObj.y);

    Console.WriteLine("Class:tx = {0},ty = {1}",
        refObj.x, refObj.y);

    // Results
    // Struct:  x = 4,  y = 4
    // Class:   x = 8,  y = 8
}

static void MultipleStruct(ValStruct obj)
{
    obj.x *= 2;
    obj.y *= 2;
}

static void MultipleClass(RefClass obj)
{
    obj.x *= 2;
    obj.y *= 2;
}

struct ValStruct
{
    public int x;
    public int y;
}

class RefClass
{
    public int x;
    public int y;
}
' VB.NET

Sub Main()

    Dim valObj As New ValStruct()
    Dim refObj As New RefClass()

    valObj.x = 4
    valObj.y = 4
    refObj.x = 4
    refObj.y = 4

    MultipleStruct(valObj)
    MultipleClass(refObj)

    Console.WriteLine("Struct:tx = {0},ty = {1}", _
            valObj.x, valObj.y)

    Console.WriteLine("Class:tx = {0},ty = {1}", _
            refObj.x, refObj.y)

    ' Results
    ' Struct:  x = 4,  y = 4
    ' Class:   x = 8,  y = 8
End Sub

Sub MultipleStruct(ByVal obj As ValStruct)
    obj.x *= 2
    obj.y *= 2
End Sub

Sub MultipleClass(ByVal obj As RefClass)
    obj.x *= 2
    obj.y *= 2
End Sub

Structure ValStruct
    Public x As Integer
    Public y As Integer
End Structure

Class RefClass
    Public x As Integer
    Public y As Integer
End Class

A little yet very important note: When comparing objects with the double equal signs (or the single sign in VB.NET,) objects are being compared internally using the System.Object.Equals() function. This function returns True if both value objects have the same value or both reference objects refer to the same object (doesn’t matter if both have the same value and are different objects.) Conversely, using the not equals operator (!= in C# and <> in VB.NET) uses the same comparison function, however, it reverses its return value (True becomes False and vice versa.)

Boxing and Unboxing

Boxing is the process of converting a value type into reference type. Unboxing on the other hand is the process of converting that boxed value type to its original state. Boxing and unboxing can be done manually (by you) or automatically (by the runtime.) Let’s see this in action.

Manual Boxing

Consider the following code:

    // C#
    byte num = 25;
    object numObj = num;
    ' VB.NET
    Dim num As Byte = 25
    Dim numObj As Object = num

The last code simply converted a value type (the byte variable) into reference type by encapsulating it into a System.Object variable. Does that really involve that passing the System.Object would be done by reference? Absolutely! (Check it yourself!)

Manual Unboxing

Now you have a boxed byte, how can you retrieve it later, i.e., restore it back to be a value type? Consider the following code:

    // C#
    // Boxing
    byte num = 25;
    object numObj = num;
    // Unboxing
    byte anotherNum = (byte)numObj;
    'VB.NET
    'Boxing
    Dim num As Byte = 25
    Dim numObj As Object = num
    'Unboxing
    Dim anotherNum As Byte = CByte(numObj)

Beware not to try to convert a boxed value to another type not its original type.

Automatic Boxing

Boxing can be done automatically by the runtime if you tried to pass that value type to a function that accepts a System.Object not that value type.

// C#
static void Main()
{
    byte num = 25;

    // Automatic Boxing
    Foo (num);
}

static void Foo(object obj)
{
    Console.WriteLine(obj.GetType());
    Console.WriteLine(obj.ToString());
}
' VB.NET
Sub Main()
    Dim num As Byte = 25

    'Automatic Boxing
    Foo(num)
End Sub

Sub Foo(ByVal obj As Object)
    Console.WriteLine(obj.GetType)
    Console.WriteLine(obj.ToString)
End Sub

Automatic Unboxing

The runtime can automatically unbox a boxed value:

// C#
static void Main()
{
    // Automatic Boxing
    object num = 25;

    // Automatic Unboxing – not really works
    Foo(num);
}

static void Foo(byte obj)
{
    Console.WriteLine(obj.GetType());
    Console.WriteLine(obj.ToString());
}
' VB.NET
Sub Main()
    ' Automatic Boxing
    Dim num As Object = 25

    ' Automatic Unboxing - works
    Foo(num)
End Sub

Sub Foo(ByVal obj As Byte)
    Console.WriteLine(obj.GetType)
    Console.WriteLine(obj.ToString)
End Sub

The difference between C# and VB.NET in the last situation is that VB.NET allows automatic unboxing while C# doesn’t. (Theoretically, VB.NET allows automatic conversion between the vast majority of types, while C# lacks this feature.)

Summary

That was a brief discussion of value types and reference types in .NET Framework. Value types are those normally when passed to a function or copied, a copy of the value is used not the original value. Therefore, changes made to that copy don’t affect the original object.

On the other hand, reference types are those when passed to a function or copied, the object itself is used. Therefore, any changes made inside the function or to the copy do affect the original object (both are the same.)

Value types in .NET are all types inherit from System.ValueType including structures, enumerations, and primitives. All other classes don’t inherit from System.ValueType are reference types.

Boxing is the process of converting a value type to reference type. Unboxing is retrieving that boxed reference type back. To box a variable simple convert it to System.Object. To unbox it, convert it back to its original type. Boxing could also occur automatically when you pass a value type to a function that accepts System.Object not the type itself.

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.