Saturday, 17 September 2011

Importing MSN/Windows Live contacts in asp.net

I am using windows live sdk to import Windows live contacts. Windows live contacts can be imported by using JavaScript, REST api but i am using server side scenario to retrieve contacts.
First of all we have to create an application on windows live which you can create from this link. press create application button by which you can get API key and secret.
Login.aspx
<script type="text/javascript">
function GoToMSN() {
            top.location.href = "https://oauth.live.com/authorize?client_id
=YOURCLIENTID
&scope=REQUIREDSCOPRES
&response_type=code&
redirect_uri=http://contacts.YOURSITEURL.com/
callback.aspx";
}</script>
<img alt="" title="Login to your msn account
and import your contacts." src="msn.jpg" onclick="javascript:GoToMSN();"/>
Callback.aspx.cs
namespace OAuthTest
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Xml;
    using System.Web.Script.Serialization;
    using System.Collections;
    using System.Data;
    public partial class Callback : System.Web.UI.Page
    {
        private const string wlCookie = "wl_auth";
        private const string clientId = "XXXXXXXXXXXXXX";
        private const string callback = "http://yoursite.com/callback1.aspx";
        private const string clientSecret = "XXXXXXXXXXXXXXXXXX";
        private const string oauthUrl = "https://oauth.live.com/token";
       
        public static int k = 0;
        public static DataTable dtMSNContacts = new DataTable();
        DataColumn dcNO = new DataColumn("SerialNo",           System.Type.GetType("System.String"));
        DataColumn dcId = new DataColumn("MSNId", System.Type.GetType("System.String"));
        DataColumn dcName = new DataColumn("Friends Name", System.Type.GetType("System.String"));
        DataColumn dcDOB = new DataColumn("Friends DOB", System.Type.GetType("System.String"));

        protected void Page_Load(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            string verifier = Request.QueryString["Code"];
            OAuthToken token;
            OAuthError error;
            if (!string.IsNullOrEmpty(verifier))
            {
                RequestAccessTokenByVerifier(verifier, out token, out error);
                gvContacts.DataSource = dtMSNContacts;
                gvContacts.DataBind();
                return;
            }
        }
        private static void RequestAccessTokenByVerifier(string verifier, out OAuthToken token, out OAuthError error)
        {
            string content = String.Format("client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&grant_type=authorization_code",
                HttpUtility.UrlEncode(clientId),
                HttpUtility.UrlEncode(callback),
                HttpUtility.UrlEncode(clientSecret),
                HttpUtility.UrlEncode(verifier));
            RequestAccessToken(content, out token, out error);
        }
        private static void RequestAccessToken(string postContent, out OAuthToken token, out OAuthError error)
        {
            token = null;
            error = null;
            HttpWebRequest request = WebRequest.Create(oauthUrl) as HttpWebRequest;
            request.Method = "POST";
            try
            {
                using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
                {
                    writer.Write(postContent);
                }
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                if (response != null)
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(OAuthToken));
                    token = serializer.ReadObject(response.GetResponseStream()) as OAuthToken;
                    if (token != null)
                    {
                        RequestContacts(token.AccessToken);
                        //return;
                    }
                }
            }
            catch (WebException e)
            {
                HttpWebResponse response = e.Response as HttpWebResponse;
                if (response != null)
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(OAuthError));
                    error = serializer.ReadObject(response.GetResponseStream()) as OAuthError;
                }
            }
            catch (IOException)
            {
            }
            if (error == null)
            {
                error = new OAuthError("request_failed", "Failed to retrieve user access token.");
            }
        }
        private static void RequestContacts(string AccessToken)
        {
            string content = String.Format("access_token={0}", HttpUtility.UrlEncode(AccessToken));
            string url = "https://apis.live.net/v5.0/me/contacts?" + content;
            //string url = "https://apis.live.net/v5.0/me/contacts?access_token=" + AccessToken;
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            //request.Method = "POST";
            request.Method = WebRequestMethods.Http.Get;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string tmp = reader.ReadToEnd();
            JavaScriptSerializer ser = new JavaScriptSerializer();
            Dictionary<string, object> dictionary = ser.Deserialize<Dictionary<string, object>>(tmp);
            DisplayDictionary(dictionary);
            response.Close();
        }
    private static bool DisplayDictionary(Dictionary<string, object> dict)
        {
            bool bSuccess = false;
            //indentLevel++;
            DataRow dr = dtMSNContacts.NewRow();
            string dob = "";
            foreach (string strKey in dict.Keys)
            {
                string strOutput = "";// "".PadLeft(indentLevel * 8) + strKey + ":";
                //tbOutput.AppendText("\r\n" + strOutput);
                object o = dict[strKey];
                if (o is Dictionary<string, object>)
                {
                    DisplayDictionary((Dictionary<string, object>)o);
                }
                else if (o is ArrayList)
                {
                    foreach (object oChild in ((ArrayList)o))
                    {
                        if (oChild is string)
                        {
                            strOutput = ((string)oChild);
                            //tbOutput.AppendText(strOutput + ",");
                        }
                        else if (oChild is Dictionary<string, object>)
                        {
                            DisplayDictionary((Dictionary<string, object>)oChild);
                            //tbOutput.AppendText("\r\n");
                        }
                    }
                }
                else
                {
                    if (o != null)
                    {
                        strOutput = o.ToString();
                        if (strKey == "id")
                        {
                            k++;
                            dr[0] = k;
                            dr[1] = strOutput;
                        }
                        else if (strKey == "name")
                        {
                            dr[2] = strOutput;
                        }
                        else if (strKey == "birth_day")
                        {
                            dob = strOutput;
                        }
                        else if (strKey == "birth_month")
                        {
                            dob += "/" + strOutput;
                        }
                        dr[3] = dob;
                    }
                }
            }


            if (dr[0].ToString() != "")
            {
                dtMSNContacts.Rows.Add(dr);
                
            }
            return bSuccess;
        }
    }
    [DataContract]
    public class OAuthToken
    {
        [DataMember(Name = OAuthConstants.AccessToken)]
        public string AccessToken { get; set; }
        [DataMember(Name = OAuthConstants.RefreshToken)]
        public string RefreshToken { get; set; }
        [DataMember(Name = OAuthConstants.ExpiresIn)]
        public string ExpiresIn { get; set; }
        [DataMember(Name = OAuthConstants.Scope)]
        public string Scope { get; set; }
    }
    public static class OAuthConstants
    {
        #region OAuth 2.0 standard parameters
        public const string ClientID = "client_id";
        public const string ClientSecret = "client_secret";
        public const string Callback = "redirect_uri";
        public const string ClientState = "state";
        public const string Scope = "scope";
        public const string Code = "code";
        public const string AccessToken = "access_token";
        public const string ExpiresIn = "expires_in";
        public const string RefreshToken = "refresh_token";
        public const string ResponseType = "response_type";
        public const string GrantType = "grant_type";
        public const string Error = "error";
        public const string ErrorDescription = "error_description";
        public const string Display = "display";
        #endregion
    }
    [DataContract]
    public class OAuthError
    {
        public OAuthError(string code, string desc)
        {
            this.Code = code;
            this.Description = desc;
        }
        [DataMember(Name = OAuthConstants.Error)]
        public string Code { get; private set; }
        [DataMember(Name = OAuthConstants.ErrorDescription)]
        public string Description { get; private set; }
    }
}
I think that this post will help you.
Thanks.

45 comments:

  1. How can I use it my localhost?

    ReplyDelete
  2. OAuthError: Where is dll? is there any project sample do you have?

    ReplyDelete
  3. Hi,
    First of all we can not run this application on local host why because MSN do not support redirect URL as localhost. and for this project we don't need any separate DLL.I think OAuthError error is coming because ur REDIRECT_URL is not same in ur application and code. I m attaching my demo application please look at it. change ur ClientId,Redirect_URL and Client_Secret and let me know if any error.

    ReplyDelete
  4. Hi, I change all of them. ERROR: &scope=REQUIREDSCOPRES.
    Can you sent me your demo project?
    mydemolink: http://hastane.pau.edu.tr/deneme/login.aspx

    ReplyDelete
  5. can u attach ur code project and ur application on MSN, so that i can look at it.I have already sent u my demo project. check ur mail once....

    ReplyDelete
  6. Hi,
    I have checked ur link it is going to MSN login page. but there is problem in ur callback page.so if u can attach ur full project then i can help u somewhat.

    ReplyDelete
  7. I haven't got any mail from you.

    ReplyDelete
  8. Ankur, I have a question, I had done this project and when I finished I realized that the e-mail is a field called email_hashes as bringing it seems encrypted or something, is this correct?

    ReplyDelete
  9. Yes, U r right, the email is encrypted in MSN because of security reasons. To convert an email into email hashes we have a simple process that is:


    Trim leading and trailing white spaces from the email address, for example, Someone@Example.org.
    Trim leading and trailing white spaces from the requesting app's client ID, for example, 0000000603DB0F.
    Concatenate the results of steps 1 and 2, for example, Someone@Example.org0000000603DB0F.
    Convert the result of step 3 to lowercase, for example, someone@example.org0000000603db0f.
    Calculate the SHA-256 value of step 4 and convert the value to its hexadecimal equivalent, for example, 6A9F...63A4. (Part of the value is omitted here for brevity.)
    Convert the results of step 5 to lowercase, for example, 6a9f...63a4. The result of this step is the email-address hash.

    for more information please visit the URL:

    http://msdn.microsoft.com/en-us/windowslive/hh278351#generating

    ReplyDelete
    Replies
    1. Ankur, thank you for your response.

      Let me get this straight. I can only know that if an email from my web site is an e-mail address registered with Live right?

      Actually what I'm wondering are all the emails of the contacts of the user authorized. This is not possible me/contacts? Imagine the scenario where I have no e-mail on my web site ok? The email is exactly what I want.

      Delete
  10. you can do it easily with JavaScript which gives ur contact list in Json format. for more information u need to study the path:
    http://msdn.microsoft.com/en-us/library/hh243641.aspx

    ReplyDelete
    Replies
    1. Ankur, I already have the contacts list, just do not get the list of emails. The list of email just got through the mail-hashes.

      In javascript I get the same result, because the email is in the scope wl.emails, but only with the authorized user and want of his contacts.

      hugs,

      Valeria

      Delete
    2. Hi,
      We can not decrypt the email hashes why because it using SHA-256 algorithm to encrypt the emails, and i found that we cant decrypt SHA-256, bacause it is one way encryption algorithm.

      If u r really needed the emails there is another method to retrieve email ids that is Social Auth.net.it is a library where we can download contacts from various sources like- Gmail,Facebook, MSN,Yahoo, LinedIn etc. U can try the demo project which is attached at the url:

      http://code.google.com/p/socialauth-net/

      Still, if u have any problems u can share....

      Delete
  11. Hi sir,

    Can you help me in rectifying Error : dtMSNContacts not exist in current page. i am new to dotnet please help me..

    Thanks,
    Raghava.

    ReplyDelete
    Replies
    1. HI Raghava,

      Check out my new code which i have added newly for the table named dtMSNContacts in Bold font. Its was an error related table dtMSNContacts declaration. It was not declared previously that's why you were getting that error.

      Delete
    2. Hi,

      can u plz help me/tell me how to import/get user's contact details i.e.,. firstname, lastname, email id, mobile no, address from hotmail and also from yahoo.

      Thanks in advance,
      Raghava

      Delete
  12. please correct the URL query strings values it work with me but grid view has't any data i need the value of :

    &scope=REQUIREDSCOPRES

    HTTP://yahootest.com.basil.arvixe.com/Callback.aspx?error=invalid_scope&error_description=The%20provided%20request%20must%20include%20a%20%27scope%27%20input%20parameter.

    ReplyDelete
    Replies
    1. Please refer follwing url for scope:

      http://msdn.microsoft.com/en-us/library/live/hh243646.aspx#types

      Delete
  13. Great sir, Thank U Very Much , it is working fine.

    Thanks,

    Raghava

    ReplyDelete
  14. Hi,
    I want to contact list with email address, but here email_hashes are coming. How to convert hash into text(email addresses) from the response of Live API for Contacts. Please help me.


    Thanks
    Khumesh Kumawat

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Process of Generating Email Hashes From Email:

      The email is encrypted in MSN because of security reasons. To convert an email into email hashes we have a simple process that is:


      Trim leading and trailing white spaces from the email address, for example, Someone@Example.org.
      Trim leading and trailing white spaces from the requesting app's client ID, for example, 0000000603DB0F.
      Concatenate the results of steps 1 and 2, for example, Someone@Example.org0000000603DB0F.
      Convert the result of step 3 to lowercase, for example, someone@example.org0000000603db0f.
      Calculate the SHA-256 value of step 4 and convert the value to its hexadecimal equivalent, for example, 6A9F...63A4. (Part of the value is omitted here for brevity.)
      Convert the results of step 5 to lowercase, for example, 6a9f...63a4. The result of this step is the email-address hash.

      for more information please visit the URL:

      http://msdn.microsoft.com/en-us/windowslive/hh278351#generating

      For Decrypting Email Hashes:

      We can not decrypt the email hashes why because it using SHA-256 algorithm to encrypt the emails, and i found that we cant decrypt SHA-256, bacause it is one way encryption algorithm.

      If u r really needed the emails there is another method to retrieve email ids that is Social Auth.net.it is a library where we can download contacts from various sources like- Gmail,Facebook, MSN,Yahoo, LinedIn etc. U can try the demo project which is attached at the url:

      http://code.google.com/p/socialauth-net/

      Delete
  15. shaleen shukla: can you please send me a demo code

    ReplyDelete
    Replies
    1. check ur mail once i have attached the demo project

      Delete
    2. do you can send me too
      thanks
      idan
      my mail is:isolimani@gmail.com

      Delete
  16. sir please send it again my mail id is : shaleenshuklass@gmail.com

    ReplyDelete
  17. Can you upload demo code please???

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. there is an error appeared::
    System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

    How can i fix it???

    ReplyDelete
  20. Hello Ankur,

    the sicalauth.net appears to be Microsoft centric solution do you have any solution for PHP, JS for hotmail facebook ?

    Thanks

    ReplyDelete
  21. This comment has been removed by the author.

    ReplyDelete
  22. hello, i've implemented this code and i get this result:
    Number: 1
    MsnID : contact.b8837e5f000000000000000000000000
    Name: dead poll

    i need send an email to MsnId from my aplication, how i can do this?

    must decode the MsnId?

    thanks

    ReplyDelete
  23. Hello Ankur Bhatnagar,

    What QueryString Code is this? Request.QueryString["Code"]
    I'm trying to test it but I don't know what is this.
    Sorry for bad English.
    Thanks

    ReplyDelete
    Replies
    1. Retriving Contacts in Live/hotmail is 3 step process.

      1. Go to the URL with cilentId, scope, responseType and redirectURL(After Retriving contacts on which page it should come.)

      https://oauth.live.com/authorize?client_id
      =YOURCLIENTID
      &scope=REQUIREDSCOPRES
      &response_type=code&
      redirect_uri=http://contacts.YOURSITEURL.com/
      callback.aspx

      2. It will return us a Request code. This Request code we will get in URL as query string as code. thats why i am using
      string verifier = Request.QueryString["Code"];

      3. using this request code we can get acess token and with the help of access token we can get the contacts

      Delete
  24. hi ankur,
    this is a great example but getting an error.

    Oops, there was a problem
    Windows Live is currently unavailable. Please try later.


    So what to do with it....its urgent

    kindly send me the demo project and tell me what modification it required.


    thanks
    Sushant

    ReplyDelete
  25. Is it possible to do the same import of contacts from Hotmail using C#. I am using a desktop application using c# on a localhost.

    ReplyDelete
  26. Callback.aspx page is showing an exception given below.

    The method or operation is not implemented.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:


    [NotImplementedException: The method or operation is not implemented.]
    Hotmail.DataContractJsonSerializer.ReadObject(Stream stream) +28
    Hotmail.Callback.RequestAccessToken(String postContent, OAuthToken& token, OAuthError& error) +251
    Hotmail.Callback.RequestAccessTokenByVerifier(String verifier, OAuthToken& token, OAuthError& error) +237
    Hotmail.Callback.Page_Load(Object sender, EventArgs e) +132
    System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
    System.Web.UI.Control.OnLoad(EventArgs e) +92
    System.Web.UI.Control.LoadRecursive() +54
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

    ReplyDelete
  27. Hello Sir when i try this code then after enter login id and pwd it shown this error:
    " Oops, there was a problem
    The client does not exist. If you are the client application developer, configure a new application through the application management site at https://manage.dev.live.com/.
    "
    But i have already created client id and secret and also given redirect domain.
    Could me help Please

    ReplyDelete
  28. Hello Sir could you explain what exacly used for &scope=REQUIREDSCOPRES ?
    I have read go thruogh your reference link but i couldn't understood exactly.
    and Also Could you send me demo project?
    My email id is [opsaharan01@gmail.com]

    ReplyDelete
  29. Hello Sir you can check error on this url[http://shutabkheen.com/hotmail.aspx]

    ReplyDelete
  30. Hi Sir, Am in a very urgent need of hotmail contact grabber can u please send me the demo code to my mail id: srikanthtumkunta@gmail.com

    ReplyDelete
  31. The remote server returned an error: (401) Unauthorized.
    Can u please help me.
    Its urgent

    ReplyDelete
  32. If its possible then plz send me your code on vidushi.shah10@gmail.com

    ReplyDelete
  33. Hi Ankur,
    this code giving me error in this line
    token = serializer.ReadObject(response.GetResponseStream()) as OAuthToken; error is
    There was an error deserializing the object of type OAuthToken. Encountered unexpected character '<'.

    how can i resolve it

    ReplyDelete
  34. Hi Ankur, If its possible then plz send me your code on santhakumar.murugarathnam@troy.co.in

    ReplyDelete