my favorite

2008/03/28

ASP.NET 取得 MSN 的聯絡人清單 (Get MSN Mail Contacts)


ASP.NET 取得 GMAIL 的聯絡人清單 (Get Google Contacts List)
以及
ASP.NET 取得 Yahoo! 的聯絡人清單 (Get Yahoo Mail Contacts)
兩篇文章之後,這一篇則是針對大家常用的Windows Live! Messenger取得所有連絡人的資訊。
其實跟Google及Yahoo都是類似的做法,主要都是使用HTTP protocol中的Request及Response取得瀏覽器以及伺服器往來的資訊。最後取得連絡人的資料後(通常是csv,或是通用xml格式)。

而這次要取得Windows Live Messenger連絡人的方式,老實說比以往還要複雜一些,因為要自己包裝SOAP envelope作為server response file(srf檔),最後再取得伺服器的回傳值(ticket)。這邊有個小問題跟Yahoo是一樣的,回傳的ticket開頭最前面的2個字元是 "t=",與當初取得Yahoo!聯絡人清單類似,只是Yahoo所得到的token前面有 "Y=" 兩個字元必須移除罷了。感謝SourceForge上讓我找到了OpenContacts.NET,否則我大概要多花一倍以上的時間去研讀各家的API。以下直接把取得ticket及擷取MSN連絡人的方法直接貼出來,這部份我有修改了一些OpenContacts.NET的內容,不過內容上並沒有什麼差異,主要是差在輸出的格式罷了 : )

WindowsLiveTicketAcquirer : 取得MSN伺服器回傳的ticket(認證)



internal class WindowsLiveTicketAcquirer {
private const string applicationId = "10"; // An arbitrary value that will be defined in the next non-alpha release

/// <summary>
/// generate SOAP envelope
/// </summary>
/// <param name="userName">user name</param>
/// <param name="password">password</param>
/// <returns>ticket</returns>
public String GetTicket(String userName, String password) {
string soapEnvelope =
@"<s:Envelope
xmlns:s = "
"http://www.w3.org/2003/05/soap-envelope""
xmlns:wsse = "
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""
xmlns:saml = "
"urn:oasis:names:tc:SAML:1.0:assertion""
xmlns:wsp = "
"http://schemas.xmlsoap.org/ws/2004/09/policy""
xmlns:wsu = "
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd""
xmlns:wsa = "
"http://www.w3.org/2005/08/addressing""
xmlns:wssc = "
"http://schemas.xmlsoap.org/ws/2005/02/sc""
xmlns:wst = "
"http://schemas.xmlsoap.org/ws/2005/02/trust"">
<s:Header>
<wlid:ClientInfo xmlns:wlid = "
"http://schemas.microsoft.com/wlid"">
<wlid:ApplicationID>"
+ applicationId + @"</wlid:ApplicationID>
</wlid:ClientInfo>
<wsa:Action s:mustUnderstand = "
"1"">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
<wsa:To s:mustUnderstand = "
"1"">https://dev.login.live.com/wstlogin.srf</wsa:To>
<wsse:Security>
<wsse:UsernameToken wsu:Id = "
"user"">
<wsse:Username>"
+ userName + @"</wsse:Username>
<wsse:Password>"
+ password + @"</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</s:Header>
<s:Body>
<wst:RequestSecurityToken Id = "
"RST0"">
<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
<wsp:AppliesTo>
<wsa:EndpointReference>
<wsa:Address>http://live.com</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<wsp:PolicyReference URI = "
"MBI""></wsp:PolicyReference>
</wst:RequestSecurityToken>
</s:Body>
</s:Envelope>"
;

const string url = @"https://dev.login.live.com/wstlogin.srf";
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/soap+xml; charset=UTF-8";
request.Timeout = 10 * 1000; // Wait for at most 10 seconds
byte[] bytes = Encoding.UTF8.GetBytes(soapEnvelope);
request.GetRequestStream().Write(bytes, 0, bytes.Length);
request.GetRequestStream().Close();
WebResponse response;
response = request.GetResponse();
string xml;
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
xml = reader.ReadToEnd();
}
response.Close();
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
XmlNamespaceManager nsManager = new XmlNamespaceManager(document.NameTable);
nsManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlNode node = document.SelectSingleNode(@"//wsse:BinarySecurityToken/text()", nsManager);
if (node == null) {
return null; // The wsse:BinarySecurityToken element is missing. Examine the xml for error information
}
else {
return node.Value;
}
}
}


LiveExtract : 取得MSN連絡人的主程式


WindowsLiveTicketAcquirer ticketAcq = new WindowsLiveTicketAcquirer();
String ticket = ticketAcq.GetTicket(userName, password).Substring(2);
UriBuilder urib = new UriBuilder();
urib.Scheme = SCHEME;
urib.Path = String.Format("/{0}/LiveContacts", userName);
urib.Host = HOST;
urib.Port = PORT;
HttpWebRequest req = WebRequest.Create(urib.Uri) as HttpWebRequest;
req.Headers.Add(HttpRequestHeader.Authorization, String.Format("WLID1.0 t=\"{0}\"", ticket));
WebResponse response = req.GetResponse();

if (response.ContentLength != 0) {
XmlDocument doc = new XmlDocument();
doc.Load(response.GetResponseStream());

#region 取得所有的 Contacts 並依結果建立 WindowsLiveContact 類別

XmlNodeList contacts = doc.SelectNodes("/LiveContacts/Contacts/Contact");
this.liveContactList = new List<WindowsLiveContact>();
XmlNode firstName, lastName, nickName, uniqueName, sortName, displayName, email, windowsLiveID, groupName;
foreach (XmlNode node in contacts) {
firstName = node.SelectSingleNode("Profiles/Personal/FirstName");
lastName = node.SelectSingleNode("Profiles/Personal/LastName");
nickName = node.SelectSingleNode("Profiles/Personal/NickName");
uniqueName = node.SelectSingleNode("Profiles/Personal/UniqueName");
sortName = node.SelectSingleNode("Profiles/Personal/SortName");
displayName = node.SelectSingleNode("Profiles/Personal/DisplayName");
email = node.SelectSingleNode("Emails/Email/Address");
windowsLiveID = node.SelectSingleNode("WindowsLiveID");
//groupName = node.SelectSingleNode("Tags/Tag");

WindowsLiveContact lc = new WindowsLiveContact();
lc.FirstName = firstName == null ? string.Empty : firstName.InnerText;
lc.LastName = lastName == null ? string.Empty : lastName.InnerText;
lc.NickName = nickName == null ? string.Empty : nickName.InnerText;
lc.UniqueName = uniqueName == null ? string.Empty : uniqueName.InnerText;
lc.SortName = sortName == null ? string.Empty : sortName.InnerText;
lc.DisplayName = displayName == null ? string.Empty : displayName.InnerText;
lc.Email = email == null ? string.Empty : email.InnerText;
lc.WindowsLiveID = windowsLiveID == null ? string.Empty : windowsLiveID.InnerText;
lc.GroupName = string.Empty;
this.liveContactList.Add(lc);
}

this.sourceTable = new DataTable();
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.DisplayName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.Email));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.FirstName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.FullName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.GroupName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.LastName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.NickName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.SortName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.UniqueName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.WindowsLiveID));
DataRow row = null;
foreach (WindowsLiveContact lc in this.liveContactList) {
row = this.sourceTable.NewRow();
row[ContactColumn.DisplayName] = lc.DisplayName;
row[ContactColumn.Email] = lc.Email;
row[ContactColumn.FirstName] = lc.FirstName;
row[ContactColumn.FullName] = lc.FullName;
row[ContactColumn.GroupName] = lc.GroupName;
row[ContactColumn.LastName] = lc.LastName;
row[ContactColumn.NickName] = lc.NickName;
row[ContactColumn.SortName] = lc.SortName;
row[ContactColumn.UniqueName] = lc.UniqueName;
row[ContactColumn.WindowsLiveID] = lc.WindowsLiveID;
this.sourceTable.Rows.Add(row);
}

this.sourceTable.AcceptChanges();

#endregion

}

7 comments:

Anonymous said...

你好:
我在写一个关于windows live contacts的程序。有些问题想请教你

我的email/msn:knyanyan@hotmail.com

方便的话能否和我联系。谢谢

阎彦

Anonymous said...

Hi, I get the error for the MSN Mail Contacts coding as below.

The remote server returned an error: (500) Internal Server Error.

Do you know how to solve it? Thanks.

Huge said...

Hi Jessie,
IIS 500 is a kind of internal server error. Please enable the debug mode if you use VS2005 or VS2008, try to find out where this error occurs. Maybe it's would be easier if you could indicate which the error message is. Thanks a lot.

Anonymous said...

您好,請問您的HOST是設定什麼呢?謝謝!
因為我的一直出現error

Anonymous said...

Ich entschuldige mich, aber meiner Meinung nach sind Sie nicht recht. Geben Sie wir werden besprechen. Schreiben Sie mir in PM. cialis cialis 20mg tadalafil [url=http//t7-isis.org]cialis preis[/url]

Anonymous said...

名前は何ですか? [url=http://japanese-garden.org]バイアグラ[/url] バイアグラ

MingYi Chen ( Miles ) said...

hi 前輩,現在我也遇到第二個朋友的問題,return error message,Host是設定cumulus.services.live.com,Path是string.Format("/{0}/LiveContacts", UserName),不知道是否有錯誤,因為有java的分享要去申請windows live api一個 applicationID ??不曉得是否真的要這麼作?? 程式新手 小明

BIO

Taipei, GuTing, Taiwan

huang47 | personal

huang47 | personal