新浪微博PC客户端(DotNet WinForm版)——功能实现分解介绍

上一篇:新浪微博PC客户端(DotNet WinForm版)—— 初探

 

说明一下:只是兴趣,并不是想发布为一个软件,说实在的,如果要作为一个软件发布,要做的工作还有很多。 

 

新浪微博API地址:http://open.t.sina.com.cn/wiki/index.php/API%E6%96%87%E6%A1%A3?retcode=0

目前提供的SDK:

 

其它的不清楚,C#的还不完善,而且不是官方的。

 

当前已实现的功能:

 1、HTTP普通鉴权(Basic Authentication)的身份验证方式,说白了就是每次访问API都要发送帐号和密码,当然是不安全的,但是相比OAuth验证方式门槛要低的多。要使用OAuth验证方式可以去看下SDK。

===》account/verify_credentials 验证当前用户身份是否合法 

 

OAuth是一种国际通用的授权方式,它的特点是不需要用户在第三方应用输入用户名及密码。OAuth的技术说明可参看官方网站 http://oauth.net。学习和研究OAuth的意义不仅仅在于新浪围脖,而是对以后开发类似的项目非常有意义和价值(如果你还不知道OAuth授权方式)。

 

验证通过则返回用户的个人信息,参照下面的API字段说明。

 

API字段说明

 

上一篇说了,API返回的结果格式有两种:XML和JSON,在调用API的时候可以指定。

这里我指定的是XML格式,实现代码如下:

登录窗体:FrmLogin.cs,可以看上一篇的截图。 

(1)把申请AppKey和AppSecret写到app.config 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<appSettings>
    
<add key="AppKey" value="3476523072"/>
    
<add key="AppSecret" value="3c909770efa6865fd5843a564545826d"/>
  
</appSettings>
</configuration>

 

要申请AppKey,需要登录新浪围脖,然后在这个地址创建应用并生成: http://open.t.sina.com.cn/apps/new

(2)创建了一个静态类,保存用户信息 

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MBClient.Entities
{
    
/// <summary>
    
/// 微博帐号资料
    
/// </summary>
    internal class UserInfo
    {
        
internal UserInfo(){ }

        
internal static string UserName { getset; }
        
internal static string Password { getset; }
        
internal static string UserNamePassword { getset; }

        
internal static int ID { getset; }

        
internal static string ScreenName { getset; }

        
internal static string Name { getset; }

        
internal static int Province { getset; }

        
internal static int City { getset; }

        
internal static string Location { getset; }

        
internal static string Description { getset; }

        
internal static string Url { getset; }

        
internal static string ProfileImageUrl { getset; }

        
internal static string Domain { getset; }

        
internal static string Gender { getset; }

        
/// <summary>
        
/// 粉丝数
        
/// </summary>
        internal static int FollowersCount { getset; }

        
/// <summary>
        
/// 关注数
        
/// </summary>
        internal static int FriendsCount { getset; }

        
/// <summary>
        
/// 微博数
        
/// </summary>
        internal static int StatusesCount { getset; }

        
internal static int FavouritesCount { getset; }

        
/// <summary>
        
/// 微博帐号日期
        
/// </summary>
        internal static string CreatedAt { getset; }

        
internal static bool Following { getset; }

        
internal static bool Verified { getset; }

        
internal static bool AllowAllActMsg { getset; }

        
internal static bool GeoEnabled { getset; }

    }
}

 

  

(3)调用API 

代码
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using MBClient.Entities;
using System.Runtime.Serialization.Json;
using System.Data;
using System.Drawing;
using MBClient.Class;

namespace MBClient.API
{
    
internal class ReadDataBySinaAPI
    {
        
internal ReadDataBySinaAPI() { }

        
/// <summary>
        
/// 根据用户登录信息登录并读取用户信息到DataSet
        
/// </summary>
        
/// <param name="url">API URL (XML Format)http://api.t.sina.com.cn/account/verify_credentials.xml?source=AppKey</param>
    
/// <param name="httpRequestMethod)">HTTP请求方式:GET或POST</param>
        
/// <returns></returns>
        internal static DataSet ReadXMLDataToDataSet(string url, string httpRequestMethod)
        {
            
try
            {
                WebResponse wr 
= BasicAuthorizationRequest(url, httpRequestMethod).GetResponse();
                DataSet ds 
= new DataSet();
                Stream receieveStream 
= wr.GetResponseStream();
                StreamReader reader 
= new StreamReader(receieveStream, Encoding.UTF8);
                ds.ReadXml(reader);
                reader.Close();
                receieveStream.Close();
                wr.Close();
                
return ds;
            }
            
catch (Exception e)
            {
                
return null;
            }
        }

        
/// <summary>
        
/// HTTP普通验证(Basic Authentication)方式
        
/// </summary>
        
/// <param name="url">API URL</param>
        
/// <param name="httpRequestMethod)">HTTP请求方式:GET或POST</param>
        
/// <returns></returns>
        private static WebRequest BasicAuthorizationRequest(string url, string httpRequestMethod)
        {
            CredentialCache mycache 
= new CredentialCache();
            mycache.Add(
new Uri(url), "Basic"new NetworkCredential(UserInfo.UserName, UserInfo.Password));
            WebRequest myReq 
= WebRequest.Create(url);
            myReq.Credentials 
= mycache;
            myReq.Headers.Add(
"Authorization""Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(UserInfo.UserNamePassword)));
            myReq.Method 
= httpRequestMethod;
            
return myReq;
        }

    }
}

 

 

 我这里直接用DataSet读取XML了,当然也可以将XML数据反序列化,后面会看到,我将返回的JSON格式的围脖信息进行了反序列化。

(4)登录窗体代码

代码
using System;
using System.Data;
using System.Windows.Forms;
using MBClient.Entities;
using MBClient.API;
using MBClient.Class;
using Sunisoft.IrisSkin;
using System.Threading;

namespace MBClient
{
    
public partial class FrmLogin : Form
    {
        
string ErrorMsg = null;
        
public FrmLogin()
        {
            InitializeComponent();
            
this.skinEngine.SkinFile = @"skin\msn.ssk";
            
this.Text = "登录" + Properties.Resources.SoftName;
        }

        
private void FrmLogin_Load(object sender, EventArgs e)
        {
            
//this.TransparencyKey = this.BackColor;
            
//各线程之间没有互相争抢控件资源的情况,设置允许跨线程访问
            CheckForIllegalCrossThreadCalls = false;
            cBoxAccountSina.Select();
            InitBackGroundWorker();
        }

        
private void InitBackGroundWorker()
        {
            backWorker.DoWork 
+= new System.ComponentModel.DoWorkEventHandler(backWorker_DoWork);
            backWorker.ProgressChanged 
+= new System.ComponentModel.ProgressChangedEventHandler(backWorker_ProgressChanged);
            backWorker.RunWorkerCompleted 
+= new System.ComponentModel.RunWorkerCompletedEventHandler(backWorker_RunWorkerCompleted);
        }

        
void backWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            
//throw new NotImplementedException();
        }

        
void backWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            
if (ErrorMsg == null)
            {
                System.Threading.Thread.Sleep(
200);
                FrmMain main 
= new FrmMain();
                
this.Hide();
                main.Show();
            }
            
else
            {
                tabControl.Visible 
= true;
                MessageBox.Show(ErrorMsg, 
"登录失败", MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
            }
        }

        
void backWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            
try
            {
                ErrorMsg 
= null;
                UserInfo.UserName 
= cBoxAccountSina.Text.Trim(); ;
                UserInfo.Password 
= txtPwdSina.Text.Trim();
                UserInfo.UserNamePassword 
= UserInfo.UserName + ":" + UserInfo.Password;

                
//source参数为申请的新浪微博App Key
                string url = Function.ACCOUNTVERIFY + "?source=" + Function.APPKEY;
                DataSet ds 
= ReadDataBySinaAPI.ReadXMLDataToDataSet(url, "GET");
                DataRow dr 
= ds.Tables[0].Rows[0];

                
#region //将用户信息保存到UserInfo
                UserInfo.AllowAllActMsg 
= bool.Parse(dr["allow_all_act_msg"].ToString());
                UserInfo.City 
= int.Parse(dr["city"].ToString());
                UserInfo.CreatedAt 
= dr["created_at"].ToString();
                UserInfo.Description 
= dr["description"].ToString();
                UserInfo.Domain 
= dr["domain"].ToString();
                UserInfo.FavouritesCount 
= int.Parse(dr["favourites_count"].ToString());
                UserInfo.FollowersCount 
= int.Parse(dr["followers_count"].ToString());
                UserInfo.Following 
= bool.Parse(dr["following"].ToString());
                UserInfo.FriendsCount 
= int.Parse(dr["friends_count"].ToString());
                UserInfo.Gender 
= dr["gender"].ToString();
                UserInfo.GeoEnabled 
= bool.Parse(dr["geo_enabled"].ToString());
                UserInfo.ID 
= int.Parse(dr["ID"].ToString());
                UserInfo.Location 
= dr["location"].ToString();
                UserInfo.Name 
= dr["name"].ToString();
                UserInfo.ProfileImageUrl 
= dr["profile_image_url"].ToString();
                UserInfo.Province 
= int.Parse(dr["province"].ToString());
                UserInfo.ScreenName 
= dr["screen_name"].ToString();
                UserInfo.StatusesCount 
= int.Parse(dr["statuses_count"].ToString());
                UserInfo.Url 
= dr["url"].ToString();
                UserInfo.Verified 
= bool.Parse(dr["verified"].ToString());
                
#endregion
            }
            
catch (Exception ex)
            {
                ErrorMsg 
= ex.Message;
            }
        }

        
private void FrmLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.ExitThread();
        }

        
private void btnLoginSina_Click(object sender, EventArgs e)
        {
            tabControl.Visible 
= false;
            backWorker.RunWorkerAsync();
        }

        
private void btnRegSina_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start(
"http://t.sina.com.cn/reg.php?ps=u3&lang=zh");
        }
    }
}

 

 

关于登录窗体的代码,说两点:

(1)使用皮肤

在你的Windows系统盘搜索IrisSkin2.dll

找到后添加到工具箱,右击工具箱——选择项——选择这个dll

然后将SkinEngine控件拖到窗体上,在代码中按照如下方式写:

this.skinEngine.SkinFile = @"skin\msn.ssk";

 

这个ssk文件我使用了网上的资源,你也可以到网上去搜,可以下载到有20种左右的皮肤,有了皮肤文件,要实现换肤功能就非常简单了。你也可以使用皮肤工具生成皮肤,如:skin++。 

 

(2)使用BackgroundWorker异步加载 :关于BackgroundWorker,MSDN说的很清楚了,这里不再赘述,http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker(v=vs.80).aspx

 

2、获取当前登录用户及其所关注用户的最新微博消息,并分页显示,这儿是我代码最多的地方,主要是由于所有显示的控件都动态加载的缘故。

今天看到新浪围脖API更新了(近一个周都没看),之前是只能传页码,默认每页返回20条数据;现在是可以传页码和返回数据的条数。

===》statuses/friends_timeline 获取当前登录用户及其所关注用户的最新微博消息 (别名: statuses/home_timeline)

 

这里在第一次加载和翻页时也使用BackgroundWorker。具体代码不贴出来了,代码太长,后面提供下载,供参考。

 

具体实现简单说一下:

根据调用接口返回的JSON数据格式化为泛型对象集合,然后遍历集合在Panel中动态添加控件显示数据,主要一点是要计算好控件的位置。

(1)围脖类  

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MBClient.Entities
{
    [DataContract]
    
internal class Status
    {
        [DataMember]
        
internal string created_at { getset; }
        [DataMember]
        
internal string id { getset; }
        [DataMember]
        
internal string text { getset; }
        [DataMember]
        
internal string source { getset; }
        [DataMember]
        
internal bool favorited { getset; }
        [DataMember]
        
internal bool truncated { getset; }
        [DataMember]
        
internal string geo { getset; }
        [DataMember]
        
internal string in_reply_to_status_id { getset; }
        [DataMember]
        
internal string in_reply_to_user_id { getset; }
        [DataMember]
        
internal string in_reply_to_screen_name { getset; }
        [DataMember]
        
internal string thumbnail_pic { getset; }
        [DataMember]
        
internal string bmiddle_pic { getset; }
        [DataMember]
        
internal string original_pic { getset; }
        [DataMember]
        
internal PostUser user { getset; }
        [DataMember]
        
internal RetweetedStatus retweeted_status { getset; }
    }
}

 

  

(2)用户类  

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MBClient.Entities
{
    [DataContract]
    
internal class PostUser
    {
        [DataMember]
        
internal string id { getset; }
        [DataMember]
        
internal string screen_name { getset; }
        [DataMember]
        
internal string name { getset; }
        [DataMember]
        
internal string province { getset; }
        [DataMember]
        
internal string city { getset; }
        [DataMember]
        
internal string location { getset; }
        [DataMember]
        
internal string description { getset; }
        [DataMember]
        
internal string url { getset; }
        [DataMember]
        
internal string profile_image_url { getset; }
        [DataMember]
        
internal string domain { getset; }
        [DataMember]
        
internal string gender { getset; }
        [DataMember]
        
internal string followers_count { getset; }
        [DataMember]
        
internal string friends_count { getset; }
        [DataMember]
        
internal string statuses_count { getset; }
        [DataMember]
        
internal string favourites_count { getset; }
        [DataMember]
        
internal string created_at { getset; }
        [DataMember]
        
internal string following { getset; }
        [DataMember]
        
internal string verified { getset; }
        [DataMember]
        
internal string allow_all_act_msg { getset; }
        [DataMember]
        
internal string geo_enabled { getset; }
    }
}

 

 

(3)转发的围脖类 

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MBClient.Entities
{
    [DataContract]
    
internal class RetweetedStatus
    {
        [DataMember]
        
internal string created_at { getset; }
        [DataMember]
        
internal string id { getset; }
        [DataMember]
        
internal string text { getset; }
        [DataMember]
        
internal string source { getset; }
        [DataMember]
        
internal string favorited { getset; }
        [DataMember]
        
internal string truncated { getset; }
        [DataMember]
        
internal string geo { getset; }
        [DataMember]
        
internal string in_reply_to_status_id { getset; }
        [DataMember]
        
internal string in_reply_to_user_id { getset; }
        [DataMember]
        
internal string in_reply_to_screen_name { getset; }
    [DataMember]
        
internal string thumbnail_pic { getset; }
        [DataMember]
        
internal string bmiddle_pic { getset; }
        [DataMember]
        
internal string original_pic { getset; }
        [DataMember]
        
internal PostUser user { getset; }
    }
}

 

  

(4)根据URL输出头像或图片 

        /// <summary>
        
/// 获取并输出图片
        
/// </summary>
        
/// <param name="imgUrl">图片URL地址</param>
        
/// <returns></returns>
        internal static Image GetAvatarImage(string imgUrl)
        {
            
try
            {
                Uri myUri 
= new Uri(imgUrl);
                WebRequest webRequest 
= WebRequest.Create(myUri);
                WebResponse webResponse 
= webRequest.GetResponse();
                Bitmap myImage 
= new Bitmap(webResponse.GetResponseStream());

                
return (Image)myImage;
            }
            
catch (Exception e)
            {
                
return null;
            }
        }

   

可以去看一下上一篇我贴出的XML数据,基本就清楚了 

 

(5)读取微博信息并反序列化   

代码
    /// <summary>
        
/// 以JSON格式字符串返回用户所有关注用户最新n条微博信息。和用户“我的首页”返回内容相同。
        
/// http://open.t.sina.com.cn/wiki/index.php/Statuses/friends_timeline
        
/// </summary>
        
/// <param name="url">API URL (JSON Format) http://api.t.sina.com.cn/statuses/friends_timeline.json?source=AppKey</param>
        
/// <param name="httpRequestMethod">HTTP请求方式</param>
        
/// <returns></returns>
        internal static string ReadJsonDataToString(string url, string httpRequestMethod)
        {
            
try
            {
                WebResponse wr 
= BasicAuthorizationRequest(url, httpRequestMethod).GetResponse();
                
string content = null;
                Stream receieveStream 
= wr.GetResponseStream();
                StreamReader reader 
= new StreamReader(receieveStream, Encoding.UTF8);
                content 
= reader.ReadToEnd();
                reader.Close();
                receieveStream.Close();
                wr.Close();
                
return content;
            }
            
catch (Exception e)
            {
                
return null;
            }
        }

        
/// <summary>
        
/// 将JSON格式字符串反序列化为Status集合对象
        
/// </summary>
        
/// <param name="url">同ReadJsonDataToString()</param>
        
/// <param name="httpRequestMethod">HTTP请求方式</param>
        
/// <returns></returns>
        internal static List<Status> DeserializeJsonToListObject(string url, string httpRequestMethod)
        {
            
try
            {
                List
<Status> listObj;
                MemoryStream stream 
= new MemoryStream();
                DataContractJsonSerializer ser 
= new DataContractJsonSerializer(typeof(List<Status>));
                StreamWriter wr 
= new StreamWriter(stream);
                wr.Write(ReadJsonDataToString(url, httpRequestMethod));
                wr.Flush();
                stream.Position 
= 0;
                Object obj 
= ser.ReadObject(stream);
                listObj 
= (List<Status>)obj;
                wr.Close();
                stream.Close();
                
return listObj;
            }
            
catch (Exception e)
            {
                
return null;
            }
        }

 

 

3、发表围脖

下面的方法还是写在ReadDataBySinaAPI这个类里。 

发表围脖分为两种情况:

(1)纯文本 ===》statuses/update 发布一条微博信息  

代码
       /// <summary>
        
/// 发表一条微博
        
/// </summary>
        
/// <param name="url">API URL http://api.t.sina.com.cn/statuses/update.json </param>
        
/// <param name="data">AppKey和微博内容  "source=123456&status=" + 微博内容; </param>
        
/// <param name="httpRequestMethod">HTTP请求方式</param>
        
/// <returns></returns>
        internal static bool PostBlog(string url, string data, string httpRequestMethod)
        {
            
try
            {
                HttpWebRequest httpRequest 
= BasicAuthorizationRequest(url, httpRequestMethod) as HttpWebRequest;
                httpRequest.ContentType 
= "application/x-www-form-urlencoded";
                Encoding encoding 
= Encoding.UTF8;//System.Text.Encoding.ASCII
                byte[] bytesToPost = encoding.GetBytes(data);//System.Web.HttpUtility.UrlEncode(data)
                httpRequest.ContentLength = bytesToPost.Length;
                Stream requestStream 
= httpRequest.GetRequestStream();
                requestStream.Write(bytesToPost, 
0, bytesToPost.Length);
                requestStream.Close();

                
return true;
            }
            
catch
            {
                
return false;
            }
        }

 

    

(2)带图片 ===》statuses/upload 上传图片并发布一条微博信息  

代码
        /// <summary>
        
/// 发布带图片的微博
        
/// ref:http://sarlmolapple.is-programmer.com/posts/22435.html
        
/// </summary>
        
/// <param name="url">微博API</param>
        
/// <param name="data">包含微博内容和图片的集合</param>
        
/// <param name="httpRequestMethod">HTTP请求方式</param>
        
/// <returns></returns>
        internal static bool PostBlogWithPic(string url, List<string> data, string httpRequestMethod)
        {
            
try
            {
                HttpWebRequest httpRequest 
= BasicAuthorizationRequest(url, httpRequestMethod) as HttpWebRequest;
                httpRequest.PreAuthenticate 
= true;
                httpRequest.AllowWriteStreamBuffering 
= true;
                
string boundary = Guid.NewGuid().ToString();
                httpRequest.ContentType 
= string.Format("multipart/form-data; boundary={0}", boundary);
                
string header = string.Format("--{0}", boundary);
                
string footer = string.Format("--{0}--", boundary);

                StringBuilder contents 
= new StringBuilder();
                contents.AppendLine(header);
                contents.AppendLine(String.Format(
"Content-Disposition: form-data; name=\"{0}\"""status"));
                contents.AppendLine(
"Content-Type: text/plain; charset=utf-8");//US-ASCII
                contents.AppendLine("Content-Transfer-Encoding: 8bit");
                contents.AppendLine();
                
//微博文字
                contents.AppendLine(data[0]);

                contents.AppendLine(header);
                contents.AppendLine(
string.Format("Content-Disposition: form-data; name=\"{0}\"""source"));
                contents.AppendLine(
"Content-Type: text/plain; charset=utf-8");//US-ASCII
                contents.AppendLine("Content-Transfer-Encoding: 8bit");
                contents.AppendLine();
                contents.AppendLine(Function.APPKEY);

                
byte[] bytesToPost = Encoding.UTF8.GetBytes(contents.ToString());

                
//微博图片
                contents = null;
                contents 
= new StringBuilder();
                contents.AppendLine(header);
                
string fileHeader = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"""pic", boundary);
                
string fileData = Encoding.GetEncoding("iso-8859-1").GetString(File.ReadAllBytes(@data[1]));

                contents.AppendLine(fileHeader);
                contents.AppendLine(
"Content-Type: application/octet-stream; charset=utf-8");
                contents.AppendLine(
"Content-Transfer-Encoding: binary");
                contents.AppendLine();
                contents.AppendLine(fileData);
                contents.AppendLine(footer);

                
byte[] bytesToPost2 = Encoding.GetEncoding("iso-8859-1").GetBytes(contents.ToString());

                httpRequest.ContentLength 
= bytesToPost.Length + bytesToPost2.Length;
                Stream requestStream 
= httpRequest.GetRequestStream();
                requestStream.Write(bytesToPost, 
0, bytesToPost.Length);
                requestStream.Write(bytesToPost2, 
0, bytesToPost2.Length);
                requestStream.Close();

                
return true;
            }
            
catch(Exception e)
            {
                
return false;
            }
        }

 

这里要注意的一点是iso-8859-1这种编码方式不支持中文,所以,把图片内容和非图片内容分开处理了。

 

(3)验证输入字数不能超过140字符 

       //计算字符串长度,中文及全角算1,其它算0.5
        internal static int GetStringLength(string text)
        {
            
int Len = 0;
            
//记录非中文、非全角字符为0.5个长度
            float charLen = 0;
            
char[] chars = text.ToCharArray();
            
for (int i = 0; i < chars.Length; i++)
            {

                
int charLength = Encoding.UTF8.GetByteCount(chars[i].ToString());
                
if (charLength == 3)
                {
                    Len
++;
                }
                
else
                {
                    
if (charLen == 0.5)
                    {
                        charLen 
= 0;
                    }
                    
else
                    {
                        charLen 
= 0.5f;
                        Len
++;
                    }
                }
            }
            
return Len;
        }

 

  

4、转发围脖 ===》statuses/repost 转发一条微博信息

用的这个方法PostBlog(),HTTP请求方式为POST。 

 

5、评论围脖 ===》statuses/comment 对一条微博信息进行评论

用的这个方法PostBlog(),HTTP请求方式为POST。 

 

6、收藏围脖 ===》favorites/create 添加收藏

用的这个方法ReadXMLDataToDataSet(),HTTP请求方式为POST。 

 

7、降低工作内存 

        /// <summary>
        
/// 设置工作内存,降低内存占用
        
/// </summary>
        
/// <param name="maxWorkingSet">内存中允许的进程的最大工作集大小(以字节为单位)</param>
        public static void SetWorkingSet(int maxWorkingSet)
        {
            System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet 
= (IntPtr)maxWorkingSet;
        }

 

HTTP请求方式,API中有说明,所以上面没有一一指出。 

 

可参考资料:

CredentialCachehttp://msdn.microsoft.com/zh-cn/library/system.net.credentialcache(v=VS.90).aspx

WebRequesthttp://msdn.microsoft.com/zh-cn/library/system.net.webrequest(v=VS.90).aspx

NetworkCredentialhttp://msdn.microsoft.com/zh-cn/library/system.net.networkcredential(v=VS.90).aspx

Basic Access Authentication:http://en.wikipedia.org/wiki/Basic_access_authenticationBasic:基本;digest简要 

 

枝枝节节的还有不少内容,不一一说了,稍后我提供源码,有兴趣的可以看下,一起讨论。

 

最后,围脖=微博,呵呵。 

 

先提供编译后的,供测试:/Files/Ferry/MBPCClient/微博客户端.rar

 

C#源码下载 

posted on 2010-12-11 01:02  Ferry  阅读(6798)  评论(19编辑  收藏  举报

导航