Developer Buzz (Dev Buzz) - Sharing My Bookmarks

16. June 2013 11:24

Musings  0 Comments

Dev Buzz is an abbreviated form of Developer Buzz which will be a carrier of my bookmarks. There is no point of saving me a bookmark if I can’t share out with other developers (this is my thought on bookmarks). Therefore, from today onward I’ll be doing a blog post week or may be monthly to share by bookmark with the rest of you guys and moreover I have a huge collection of funny programmer pics which also accompany my bookmarks. Hope you all like this.

 No Rating

HTML5 Video - Capture And Upload Image To Azure Storage

2. June 2013 23:46

ASP.NET Cloud HTML5 Web Windows Azure  2 Comments

I was exploring Github for some image effects/filters and I found some but still keep exploring and found an interesting plugin called face-detection. This plugin uses HTML5 getUserMedia to use your web camera only if your browser supports it. Unfortunately, IE10 still doesn’t support it. This seems cool to me, so I created a sample application to test it. This sample application will let you preview the video using your web camera and allows you to capture the image from your web camera and upload  it to the Azure storage. The javascript code for the HTML5 video I am using is from David Walsh’s post. Not every browser supports getUserMedia, so if the user is not using the browser which supports getUserMedia then you can show an alert message to the user notifying about the browser incompatibility. Here is the function which will check your browser compatibility for getUserMedia.

function hasGetUserMedia() {
 // Note: Opera is unprefixed.
 return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
 navigator.mozGetUserMedia || navigator.msGetUserMedia);
}
 
if (hasGetUserMedia()) {
 // Good to go!
} else {
 alert('getUserMedia() is not supported in your browser');
}

To know more and explore more what you can do with getUserMedia visit HTML5Rocks. Moving further, I have a normal HTML page where initially I am placing 3 elements on the page. One is a video tag which will show the stream from the web camera attached to your machine or your laptop camera. Second, is the canvas tag which is used to show the image captured from the web camera and the third one is the normal button which will let me capture the image at my will on its click.

<video autoplay id="video" width="640" height="480"></video>
<input id="snap" type="button" value="Click" />
<canvas id="canvas" width="640" height="480"></canvas>

Notice the autoplay property in the video tag. I have set it because I don’t want the video to be frozen as soon as it started. To make the video work I am using David Walsh’s code as it is without any changes.

window.addEventListener("DOMContentLoaded", function () {
    // Grab elements, create settings, etc.
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        video = document.getElementById("video"),
        videoObj = { "video": true },
        errBack = function (error) {
            console.log("Video capture error: ", error.code);
        };
 
    if (navigator.getUserMedia) { // Standard
        navigator.getUserMedia(videoObj, function (stream) {
            video.src = stream;
            video.play();
        }, errBack);
    } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
        navigator.webkitGetUserMedia(videoObj, function (stream) {
            video.src = window.webkitURL.createObjectURL(stream);
            video.play();
        }, errBack);
    }
 
    // Trigger photo take
    document.getElementById("snap").addEventListener("click", function () {
        context.drawImage(video, 0, 0, 640, 480);
    });
}, false);

In the above script, you can see that it first checks if the browser or navigator has the getUserMedia support. if you see there are two conditions one for the standard and other one with the webkit prefix. In the end, the click event on the button which will let me capture the image.

When you view the application in the browser, the browser will prompt you whether you want to allow or deny the application to use the web camera.

You cannot run this just by double-clicking the file due to security reasons. You must access the web page from the server itself, either from within the Visual Studio development server, from IIS or by publishing the file on your production server. It can be annoying for many users to grant the access to the camera every time they access the page. You can save the user consent if you are using https. If you plan to stick with http, you will not be able to do this.

Looking in the address bar again, you will notice that the fav icon of the web application, changed to an animated icon. It is a little red dot which keeps on flashing notifying the user that the camera is in use. If you plan to block the access to the camera permanently or temporarily, you can then click the camera icon which is on the right hand side of the address bar.

When you click the icon you will be prompted with options to continue allow the access to the camera or always block the camera. Also if you notice the camera option, you will see that it is showing me two devices or camera attached to the machine. I build this application on my laptop so I am able to the integrated camera which is the front facing camera of my laptop and the second one is the USB camera I have plugged on my laptop’s USB port. I can choose to use any one of these. If you make any changes to these settings and click on done, you will be asked to reload the page.

This is how my web page looks.

The click button is at the bottom right hand side will let me take a snap of the feed coming from my camera. When I click the Click button, the image is captured and show on the canvas we have added on the page. This is my web page after I took the snap from my web camera.

The second image (at the bottom) is the image on the canvas that is snapped from the camera. Now I want to upload the image to my Azure cloud storage. If you look at the address bar, you’ll notice that I have used normal HTML page. It’s you wish if you want to use a simple HTML page or a web form. Both works good. The problem I am going to face with web forms is if I am going to upload the snapped image to my cloud storage or to my server repository, the page will post-back which is not cool at all. So I am going to accomplish it by making an AJAX call. Add a HTML button to your page and on its click event upload the file to the cloud.

I have the image on my canvas, therefore you just cannot retrieve the image Base64 string just like that. I am going to extract the Base64 string of the image from the canvas and pass it as a parameter. The server method will then convert the Base64 string to stream and upload it to the cloud storage. Here is the jQuery AJAX call.

function UploadToCloud() {
    $("#upload").attr('disabled', 'disabled');
    $("#upload").attr("value", "Uploading...");
    var img = canvas.toDataURL('image/jpeg', 0.9).split(',')[1];
    $.ajax({
        url: "Camera.aspx/Upload",
        type: "POST",
        data: "{ 'image': '" + img + "' }",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function () {
            alert('Image Uploaded!!');
            $("#upload").removeAttr('disabled');
            $("#upload").attr("value", "Upload");
        },
        error: function () {
            alert("There was some error while uploading Image");
            $("#upload").removeAttr('disabled');
            $("#upload").attr("value", "Upload");
        }
    });
}

The line 4 in the above script is the one which will get the Base64 string of the image from the canvas. The string is now in the variable named img which I am passing as a parameter to the Upload web method in my code-behind page. You can use web service or handler or maybe a WCF service to handle the request but I am sticking with page methods. Before you can actually make use of the Azure storage, you have to add reference of the Azure Storage library from NuGet. Fire the below NuGet command to add the Azure Storage reference to your application.

Install-Package WindowsAzure.Storage

After the package/assemblies are referenced in your code, add the below namespaces.

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using System.IO; //For MemoryStream
using System.Web.Services; //For WebMethod attribute

These all the namespace will help me to connect to my local cloud storage emulator or to my live cloud storage. This is my upload method which will upload the file to my live cloud storage.

[WebMethod]
public static string Upload(string image)
{
    string APIKey = "LFuAPbLLyUtFTNIWwR9Tju/v7AApFGDFwSbodLB4xlQ5tBq3Bvq9ToFDrmsZxt3u1/qlAbu0B/RF4eJhpQUchA==";
    string AzureString = "DefaultEndpointsProtocol=https;AccountName=[AccountName];AccountKey=" + APIKey;
 
    byte[] bytes = Convert.FromBase64String(image);
 
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(AzureString);
 
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
 
    CloudBlobContainer container = blobClient.GetContainerReference("img");
 
    string ImageFileName = RandomString(5) + ".jpg";
 
    CloudBlockBlob imgBlockBlob = container.GetBlockBlobReference(ImageFileName);
 
    using (MemoryStream ms = new MemoryStream(bytes))
    {
        imgBlockBlob.UploadFromStream(ms);
    }
 
    return "uploaded";
}

I have decorated this method with WebMethod attribute. This is necessary as I have to call this method from jQuery/javascript. Also the method should be public static. The AzureString  serves as the connection string for the cloud storage. You have to change the [AccountName] in the connection string to the storage account name. In my case it is propics. The method accepts the Base64 string as a parameter.

Storage is something different than that of the container and therefore I have to create a container which actually holds my images which I upload to the cloud storage. I am not explaining the code completely but it is not that complicate. To upload the file to the storage I must have a file name. The image I get from the canvas is just a Base64 string and does not have a name, so I have to give it a name. I have a random function which will generate the random string which I will be using as a file name for my image file.

//stole from http://stackoverflow.com/questions/1122483/c-sharp-random-string-generator
private static string RandomString(int size)
{
    Random _rng = new Random();
    string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
    char[] buffer = new char[size];
 
    for (int i = 0; i < size; i++)
    {
        buffer[i] = _chars[_rng.Next(_chars.Length)];
    }
 
    return new string(buffer);
}

This is a small function which I stole from Stackoverflow to generate random name for my image file. So this is it and when I click the upload button on my page.

Now if I check my cloud storage I have can see the uploaded files.

This is just a simple example to get you started. You can give some cool effects before you can actually upload the files. If you do a quick search you’ll find plenty of links which will let you give some cool effects to your pictures. I came across a brilliant plugin called filtrr. You should try it and come up with something which is awesome or may be something like Instagram. Hope this help some folks out there.

References:

 No Rating

Building MVC Application With Multiple Database Support Using Ninject

13. May 2013 14:33

API ASP.NET MVC C#  0 Comments

I used to have BlogEngine.NET as my blogging platform before switching to WordPress, and that is because of my poor hosting provider who can’t afford few MBs on the shared hosting plans. I like BlogEngine.NET a lot because it is in .NET and on the other hand WordPress is on PHP which I don’t know. BlogEngine.NET is still evolving and is getting better with every release. BlogEngine.NET supports multiple databases like SQL Server, SQL Server CE, MySQL, XML file, VistaDB and may be few more. As it is open-source, I jumped into the code and found it to be a bit hard to get through its implementation. To be frank, I didn’t look into that deep!! but it is not implementing what I was expecting it was. What I was expecting was the use of dependency injection (DI).

I am constantly working on new projects open-source and freelanced and few of them are for fun. The application I am working on right now requires a multiple DB support. The main problem I am going to face is not writing different functions for different DB operations, but having them integrated at the time when the user selects the database. BlogEngine.NET implements it pretty impressively, but I was expecting something else. For my project I will be using Ninject. If you want to do for your application, then this is how you can do it.

Create a new MVC internet application. First thing that we need to do is to add Ninject reference to the project by firing the below Nuget command. Remember that for MVC application you need to use Ninject.MVC3 and for other applications you need to use Ninject only: Install-Package Ninject

Install-Package Ninject.MVC3

When the library is installed successfully, you will notice a file under App_Start folder named NinjectWebCommon.cs. This is a very important file and we will look into it this later when we are done with other things.

What I am trying to achieve here is that my application would be able to support multiple databases and I also want to keep my code clean. I don’t want to handle it using some if..else conditions. Ninject does the work for me pretty well here. I will create an interface that will have all the functions which my wrapper classes will implement. For the sake of simplicity for this example I am going to perform basis CRUD operations, I will be writing code to implement two database support and will be using a custom written ORM called Dapper to communicate to the DB (you can use EF if you wish). I will name my interface IDBProvider.

public interface IDBProvider
{
    bool Add(Friends friend);
    bool Update(int Id, Friends friend);
    bool Delete(int Id);
    IEnumerable ListFriends();
    Friends ListFriend(int Id);
}

As you can see from the above code that I am using Friends model to save details of my friend. So here is my model.

public class Friends
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Skype { get; set; }
}

After this I am going to have support for two databases, SQL Server and SQL Server CE (4.0). For this I will create 2 classes which will implement the IDBProvider interface naming SQLHelper.cs and SQLCEHelper.cs respectively.

SQLHelper.cs

public class SQLHelper : IDBProvider
{
    string ConStr = ConfigurationManager.ConnectionStrings["Con"].ConnectionString;
 
    public bool Add(Friends friend)
    {
        bool Added = false;
 
        try
        {
            using (SqlConnection con = new SqlConnection(ConStr))
            {
                string insertSQL = "INSERT INTO Friends(Name, Email, Skype) VALUES (@Name, @Email, @Skype)";
                con.Open();
                con.Execute(insertSQL, new
                {
                    friend.Name,
                    friend.Email,
                    friend.Skype
                });
 
                Added = true;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
 
        return Added;
    }
 
    public IEnumerable ListFriends()
    {
        try
        {
            using (SqlConnection con = new SqlConnection(ConStr))
            {
                string strQuery = "Select Id, Name, Email, Skype FROM Friends";
                con.Open();
                var AllFriends = con.Query(strQuery);
 
                return AllFriends;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
    }
 
    public Friends ListFriend(int Id)
    {
        try
        {
            using (SqlConnection con = new SqlConnection(ConStr))
            {
                string strQuery = "SELECT Id, Name, Email, Skype FROM Friends WHERE Id=" + Id;
                con.Open();
                var friend = con.Query(strQuery).Single();
                return friend;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
    }
 
    public bool Update(int Id, Friends friend)
    {
        bool Update = false;
        try
        {
            using (SqlConnection con = new SqlConnection(ConStr))
            {
                string strUpdate = "UPDATE Friends SET Name = @Name, Email = @Email, Skype = @Skype WHERE Id = " + Id;
                con.Open();
                con.Execute(strUpdate, new
                {
                    friend.Name,
                    friend.Email,
                    friend.Skype
                });
 
                Update = true;
            }
 
        }
        catch (Exception x)
        {
            throw x;
        }
 
        return Update;
    }
 
    public bool Delete(int Id)
    {
        bool Deleted = false;
        try
        {
            using (SqlConnection con = new SqlConnection(ConStr))
            {
                string strDelete = "DELETE FROM Friends WHERE Id = " + Id;
                con.Open();
                int i = con.Execute(strDelete);
                if (i > 0)
                    Deleted = true;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
 
        return Deleted;
    }
}

SQLCEHelper.cs

public class SQLCEHelper : IDBProvider
{
    string ConStr = ConfigurationManager.ConnectionStrings["Con"].ConnectionString;
 
    public bool Add(Friends friend)
    {
        bool Added = false;
 
        try
        {
            using (SqlCeConnection con = new SqlCeConnection(ConStr))
            {
                string insertSQL = "INSERT INTO Friends(Name, Email, Skype) VALUES (@Name, @Email, @Skype)";
                con.Open();
                con.Execute(insertSQL, new
                {
                    friend.Name,
                    friend.Email,
                    friend.Skype
                });
 
                Added = true;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
 
        return Added;
 
    }
 
    public bool Update(int Id, Friends friend)
    {
        bool Update = false;
        try
        {
            using (SqlCeConnection con = new SqlCeConnection(ConStr))
            {
                string strUpdate = "UPDATE Friends SET Name = @Name, Email = @Email, Skype = @Skype WHERE Id = "+Id;
                con.Open();
                con.Execute(strUpdate, new
                {
                    friend.Name,
                    friend.Email,
                    friend.Skype
                });
 
                Update = true;
            }
 
        }
        catch (Exception x)
        {
            throw x;
        }
 
        return Update;
    }
 
    public bool Delete(int Id)
    {
         bool Deleted = false;
         try
         {
             using (SqlCeConnection con = new SqlCeConnection(ConStr))
             {
                 string strDelete = "DELETE FROM Friends WHERE Id = " + Id;
                 con.Open();
                 int i = con.Execute(strDelete);
                 if (i > 0)
                     Deleted = true;
             }
         }
         catch (Exception x)
         {
             throw x;
         }
 
         return Deleted;
    }
 
    public IEnumerable ListFriends()
    {
        try
        {
            using (SqlCeConnection con = new SqlCeConnection(ConStr))
            {
                string strQuery = "Select Id, Name, Email, Skype FROM Friends";
                con.Open();
                var AllFriends = con.Query(strQuery);
 
                return AllFriends;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
    }
 
    public Friends ListFriend(int Id)
    {
        try
        {
            using (SqlCeConnection con = new SqlCeConnection(ConStr))
            {
                string strQuery = "SELECT Id, Name, Email, Skype FROM Friends WHERE Id=" + Id;
                con.Open();
                var friend = con.Query(strQuery).Single();
                return friend;
            }
        }
        catch (Exception x)
        {
            throw x;
        }
    }
}

The question now here is that how would the application will know which DB to use as a data store? For this I made few settings in my web.config file. In the appSettings section I added a setting that will hold the value which we use as an identifier and connect to the DB. You can have different approach to achieve this, it is not at all necessary to use what I have used here. My app setting in web.config looks something like this:

<add key="DBProvider" value="SQL"/>

When reading this settings I will be dynamically calling or injecting the code on the basis of the value of DBProvider in my app settings. In this case I will bind SQLHelper when the value is SQL and SQLCEHelper when the value is SQLCE. In the start of the tutorial I mentioned about the NinjectWebCommon.cs file in the App_Start folder. Here we will be looking into CreateKernel method as this is the place where I implement my helper classes.

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
 
    if (ConfigurationManager.AppSettings["DBProvider"].ToString().ToLower() == "sql")
    {
        kernel.Bind<IDBProvider>().To<SQLHelper>();
    }
    else
    {
        kernel.Bind<IDBProvider>().To<SQLCEHelper>();
    }
 
    RegisterServices(kernel);
    return kernel;
}

Notice the highlighted code. I am conditionally binding the implementation on the basis of the settings in my web.config file. What exactly is happening here is that the code is being injected depending on the conditions and this is why we call it dependency injection.

To get the benefit of this, we need to make few changes to our controller.

private readonly IDBProvider _dbProvider;
 
public HomeController(IDBProvider dbProvider)
{
    this._dbProvider = dbProvider;
}

I have a default constructor which takes the IDBProvider as a parameter. The IDBProvider object is all we need which provides us all its implementation. To add a friend to DB you just have to call the Add method like _dbProvider.Add(friend). Same for edit, update, delete and list all the friends. You noticed that no where in the code I have made use of the SQLHelper.cs or SQLCEHelper.cs classes. This is the awesomeness of DI.

This is all it and now your application is flexible enough to use multiple databases. I strongly recommend you to read the documentation on Ninject at Ninject.org as it is vast and can be a life saver in many scenarios.

 No Rating

ASYNC Controller In MVC 4

30. April 2013 22:17

.NET Framework ASP.NET MVC C# Visual Studio  0 Comments

I have build many small applications so far in MVC to help myself in understanding the framework more deeply. Now I am planning to write a blog engine on MVC. It will not be an easy task but I will be going to learn a lot of things. As I was planning things ahead I came across a problem where I have to load my blog stats like FeedBurner readers, Facebook page likes, Google +1 count, twitter followers inside a div on the page. The problem I see here is that I am going to make multiple cross-domain calls in order to get the stats. I can’t avoid that though but this will cause my blog to load slowly. I know about Async and Task Parallel Library(TPL) but the question is how do I implement this in my application? I do a quick web search and found something which is called Async controller in MVC4. You can also have AsynController in MVC3 but that is not pretty if you start comparing it with MVC4.

For the simplicity of the tutorial I am going to make 2 calls: get twitter followers count and facebook page likes. In MVC3, if you want to perform Async operations then you have to inherit your controller with AsyncController like this.

public class HomeController : AsyncController

But MVC4 is much cleaner. Let’s take a look at the default implementation of the calls I am making to Twitter and Facebook to get the follower count and page likes respectively. Here are my 2 methods in HomeController.

private string GetTwitterFollowersCount(string Username)
{
    XDocument xdoc = XDocument.Load("http://api.twitter.com/1/users/show.xml?screen_name=" + Username + "&include_entities=false");
    return (from item in xdoc.Descendants("user")
            select item.Element("followers_count").Value)
            .SingleOrDefault();
}
 
private string GetFacebookLikes(string FaceBookPageURL)
{
    string uri = "https://api.facebook.com/method/fql.query?query=select%20%20like_count,%20total_count,%20share_count,%20click_count%20from%20link_stat%20where%20url=%22" + FaceBookPageURL + "%22";
    return Convert.ToString((from elem in XElement.Load(uri).Descendants()
                   where elem.Name.LocalName == "like_count"
                   select elem).First<XElement>().Value);
}

Nothing fancy in the above two methods. When I call these 2 methods one after the other, they will just get the data from a different source and render the result in the view. That’s fine as it’s my requirement. Now when I run my application it now takes a longer time to render the view. Before I explain this further take a look at my Index().

public ActionResult Index()
{
    Stopwatch watch = new Stopwatch();
    watch.Start();
    ViewBag.TwitterFollowers = GetTwitterFollowersCount("audi");
    ViewBag.FacebookLikes = GetFacebookLikes("http://facebook.com/audi");
    watch.Stop();
    Int64 elapsedTime = watch.ElapsedMilliseconds;
    ViewBag.Time = elapsedTime.ToString();
    return View();
}

This is because Controllers are synchronous by default and it will process the request one after the other i.e. it will wait for the first task to complete and then move on to the next task. In my case the controller will execute the GetFollowersCount method and only after the completion of this method it will shift to the next method GetFacebookLikes. This could be a long running task or just imagine if you are retrieving heavy data from different sources. The view or the page will not render till the execution of both the methods will not get completed. To get a rough idea of the time elapsed in making synchronous calls in the above controller, I have used StopWatch(System.Diagnostics) class. I don’t know how accurate, but I still used it to have an approximate idea of the time. This is the output of the above code.

It took 1588ms to complete 2 requests. Now if I implement async in the controller I will see a drastic improvement. It is not just the controller ActionResult which I have to change to support async calls but I also have to update the 2 methods which I am using to collect the stats. Here are my updated methods.

private Task<string> GetTwitterFollowersCountAsync(string Username)
{
    return Task.Run(() =>
    {
        XDocument xdoc = XDocument.Load("http://api.twitter.com/1/users/show.xml?screen_name=" + Username + "&include_entities=false");
        return (from item in xdoc.Descendants("user")
                select item.Element("followers_count").Value).SingleOrDefault();
    });
}
 
private Task<string> GetFacebookLikesAsync(string FaceBookPageURL)
{
    return Task.Run(() =>
    {
        string uri = "https://api.facebook.com/method/fql.query?query=select%20%20like_count,%20total_count,%20share_count,%20click_count%20from%20link_stat%20where%20url=%22" + FaceBookPageURL + "%22";
        return Convert.ToString((from elem in XElement.Load(uri).Descendants()
                                 where elem.Name.LocalName == "like_count"
                                 select elem).First<XElement>().Value);
    });
}

Pay attention to the GetTwitterFollwersCountAsync and GetFacebookLikesAsync return type. Previously they were only string, and now I have changed their return type to Task. I have put the code inside Task.Run() as it will queues the specified work to run on the Thread Pool and returns a Task(TResult) handle for that work. I have changed the ActionResult to handle the async feature. As you can see that this controller method does not return ActionResult instead it return Task. Here is my updated ActionResult.

public async Task<ActionResult> Index()
{
    Stopwatch watch = new Stopwatch();
    watch.Start();
    Task<string> twitterFollowers = GetTwitterFollowersCountAsync("audi");
    Task<string> facebookLikes = GetFacebookLikesAsync("http://facebook.com/audi");
    await Task.WhenAll(twitterFollowers, facebookLikes);
    ViewBag.TwitterFollowers = await twitterFollowers;
    ViewBag.FacebookLikes = await facebookLikes;
    watch.Stop();
    Int64 elapsedTime = watch.ElapsedMilliseconds;
    ViewBag.Time = elapsedTime.ToString();
    return View();
}

The code is almost the same but 3 lines are making a difference (highlighted). Task will hold the value returned from the updated async methods. MSDN defines the await operator as:

The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.

Task.WhenAll() will creates a task that will complete when all of the supplied tasks have completed. This actually parallelize the request. Lets check the output and compare both.

The difference is noticeable…607ms!! is half way down and a huge performance benefit. This is a small example and the real performance can be noticed when you work with real scenarios. I have used MVC4 with .NET 4.5 to use awesomeness of asynchronous controller. I hope this gives you an idea on how you can use async controllers in MVC4.

 No Rating

Using Skydrive REST API

28. April 2013 21:52

API Cloud Microsoft  Projects Utils  11 Comments

I have created a wrapper class to simplify my work with REST API. I assume that you will be using a web application. First step is to create an application at dev.live.com. Once the application is created you will have the ClientID, Client Secret and Redirect domain. We will be using a ClientID and Redirect domain. Remember that the Redirect domain value cannot have localhost. You must provide a correct domain name as after successful authentication you, the user will be redirected to the domain along with the access token.

In the response you will get the access token which will be available to you for the next 3600 seconds. The access token will be in the returning URL of your domain. In my case it is http://midnightprogrammer.net/#access_token=EwBIA…. I will then retrieve the access token and pass it to my wrapper which will do the work for me.

Time to look and understand the code a bit. I have been using SkyDrive a lot for backup and sharing files and I also access SkyDrive from a web application I have built. But the code is pretty messy and needs revision. So I created a wrapper around the API.

First I need to authenticate the user with his/her live credentials with correct scopes. If scopes are wrong you will not be able to perform actions to the SkyDrive. To learn more about scopes read here. As I am working with SkyDrive I am using 2 scopes wl.signin and wl.skydrive_update. wl.skydrive_update is necessary if you want to have write access to SkyDrive. The SkyDriveAPI wrapper class has the Authenticate method which will redirect you to authentication screen of live service. Once you enter your credentials you will then be redirected to the domain (the domain you provided while you created the application) along with the access token. Here is the sample code:

public void Authenticate()
{
    string authorizeUri = AuthUri;
    authorizeUri = authorizeUri + String.Format("?client_id={0}&", _ClientId);
    authorizeUri = authorizeUri + String.Format("scope={0}&", "wl.signin,wl.skydrive_update");
    authorizeUri = authorizeUri + String.Format("response_type={0}&", "token");
    authorizeUri = authorizeUri + String.Format("redirect_uri={0}", HttpUtility.UrlEncode(_SiteURL));
    this.AuthURI = authorizeUri;
}

This is an insight of the wrapper class. In the actual scenario you will never be using it this way:

SkyDrive drive = new SkyDrive(ClientID, Site URL);
drive.Authenticate();
Response.Redirect(drive.AuthURI);

In the constructor of the SkyDrive class, the first parameter will be your ClientID and the second one will be the Site URL or the redirect domain. After this the SkyDrive class object drive (whatever the name you give) will call the Authenticate method to generate the URL with all the required parameters and store the URL in the public variable called AuthURI, which I used to redirect the user to authenticate using his credentials.

Now Once the user is authenticated you will be provided with the access token in the URL. It depends on you how you are going to fetch it. Once you fetch the access token you then need to keep it safe. To make sure that the access token remains with your API calls, save it like this:

drive.AccessToken = "EwBIA.....";

Once you have the access token, you are all good to make your first call to SkyDrive. For the simplicity, I am making a request to call get the basic user information.

User usr = drive.GetUserInfo();

Moreover you can also list all the folders in your SkyDriver with this simple call.

Folder driveFolders = new Folder();
foreach (var folder in driveFolders)
{
    Response.Write(folder.Value + " " + folder.Key +"<br/>");
}

The above code returns a Dictionary which contains the name of the folder and id of the folder. You’ll need the folder id in order to list down all the files in the folder. To list down all the files in a folder use the below code.

FolderContent content = drive.ListFolderContent("folder.77e33dba68367a16.77E33GBA68467A16!2189");
for (int i = 0; i < content.Files.Count; i++)
{
    Response.Write(content.Files[i].name);
}

It is not just the name of the files you get but you get the complete properties of the file. So you can play around with that too.

Coming to the most searched feature of SkyDriver REST API is to how to upload a file using REST API. The MSDN states that you can upload the files to SkyDriver by making HTTP POST or HTTP PUT requests. Here is how I am doing it inside my wrapper class.

public bool UploadFile(string FolderID, string FilePath)
{
    bool Uploaded = false;
    try
    {
        byte[] fileBytes = System.IO.File.ReadAllBytes(FilePath);
        string UploadURI = BaseURI + FolderID + "/files/" + Path.GetFileName(FilePath) + "?access_token=" + AccessToken;
 
        var request = (HttpWebRequest)HttpWebRequest.Create(UploadURI);
        request.Method = "PUT";
        request.ContentLength = fileBytes.Length;
 
        using (var dataStream = request.GetRequestStream())
        {
            dataStream.Write(fileBytes, 0, fileBytes.Length);
        }
 
        string status = (((HttpWebResponse)request.GetResponse()).StatusDescription);
 
        if (status.ToLower() == "created")
        {
            Uploaded = true;
        }
 
        return Uploaded;
    }
    catch (Exception)
    {
        return false;
    }
}

I am using a PUT method to upload files to SkyDrive. At this moment I have not implemented the POST method. But in near future I will. If you are using my wrapper class then the just use a single line of code to upload a file to a particular folder.

bool uploaded = drive.UploadFile("folder.77e33dba68367a16.77E33DUA68567A16!104", "D:\\walls\\flowers_442.jpg");

Calling the UploadFile method will upload a file to the folder. The first parameter in the above method is the folder id where you want to upload the folder and the second one is the local file path.

I am currently working and trying to understand the REST API and its features. I will include other functions as more and more I learn about them.

The SkyDrive API Wrapper is hosted on GitHub. Fork it, change it, customize it as you wish. And if you have or found something good, then please do let me know.

I want to give the credit to Christophe Geers for his post which gives me an insight of the API.

 No Rating

Visit blogadda.com to discover Indian blogs Computers Blogs