Skip to content
Lu Rongkai edited this page Jan 10, 2013 · 5 revisions

#欢迎使用

新浪微博开放平台API for .Net SDK是一个基于新浪微博开放平台第二版API接口进行封装的一个针对.Net 2.0/3.5/4.0平台的软件开发包。使用本SDK有助于.Net平台开发人员使用C#, VB.Net等快速、简便地开发微博相关应用。SDK同时支持Windows应用程序开发及Web开发。 Visual Studio版本选择的提示

  • Visual Studio 2005 - VS2005要写很长很长的对象名,例如:NetDimension.Weibo.Entities.status.Entity,而且每个返会值都要写一次哦。如果不嫌烦,继续选择VS2005。
  • Visual Studio 2008 - VS2008不支持命名实参和可选实参,SO,你的代码里必须指定每一个API接口所需的参数。写吧,你时间多不嫌累的话。
  • Visual Studio 2010 - 这才是我推荐的
  • Visual Studio 2012 - 你值得拥有

#从这里开始

  1. 进入新浪开放平台,为即将开发的微应用申请一个开发用的AppKey(注意:开发阶段无需提交审核)。
  2. 在新浪开放平台“我的应用”->“应用信息”->“高级信息”->"OAuth2.0 授权"中绑定正确的回调地址。
  3. 记录申请到的应用AppKeyAppSecret及回调地址。
  4. 下载页面下载最近编译的DLL文件或者也可以从源代码页面直接下载最新的项目源代码来自己编译DLL。
  5. 选择好.net目标框架版本并在项目中添加对应版本的NetDimension.Weibo.dll文件的引用。
  6. 实例化授权类,选择合适的方法来进行授权。
  7. 授权成功后通过API操作组件调用各种接口。

如果还是搞不清AppKey, AppSecret和回调地址,请下载在线教学视频

#使用实例

若用户是初次使用应用,那么就需要进行授权操作。

实例化对象

var oauth = new NetDimension.Weibo.OAuth("<AppKey>", "<AppSecret>", "<回调地址>");

这里请注意,SDK中提供了两种授权方式。一种是标准的方式,另一种是模拟方式。

  • 标准方式按照新浪官方的要求一步一步完成各项授权的步骤。一般比较适用于Web项目。
  • 模拟方式是将上述步骤集合进一个方法中一次性完成授权操作。使用这种方法只需提供微博账号及密码作为参数即可完成授权。形式上有点像官方GetAccessToken方法中GrantTypepassword的授权方式,但这种模拟提交的方法理论上还是采用了GrantTypeAuthorizationCode的授权方式,只是通过模拟标准方式的操作来完成授权。跟官方文档中使用用户名和密码登录的接口无关(官方客户端登录方式需要授权)。所以,模拟方式更适用于没有得到官方审核的客户端形式应用的授权和登录。

##标准方式授权

//第一步获取新浪授权页面的地址
var authUrl = oauth.GetAuthorizeURL(); //VS2008需要指定全部4个参数,这里是VS2010等支持“可选参数”的开发环境的写法
/* 第二步访问这个地址。
 * Console用Process.Start()方法,Web用Response.Redirect()方法。
 * 方法很多,自行选择。
 * 本例采用控制台的形式来演示代码。*/
System.Diagnostics.Process.Start(authUrl);
Console.Write("填写浏览器地址中的Code参数:");
var code = Console.ReadLine();
var accessToken = oauth.GetAccessTokenByAuthorizationCode(code);
//打印AccessToken
Console.WriteLine(accessToken.Token); 
//或者
Console.WriteLine(oauth.AccessToken);
if (!string.IsNullOrEmpty(accessToken.Token))
{
	var Sina = new NetDimension.Weibo.Client(oauth);
	var uid = Sina.API.Account.GetUID(); //调用API中获取UID的方法
	Console.WriteLine(uid);
}

##模拟方式授权

//相对于标准授权,模拟授权的方式就要简洁得多。
bool result = oauth.ClientLogin("<微博账号>", "<登录密码>");
if (result) //返回true授权成功
{
	Console.WriteLine(oauth.AccessToken); //还是来打印下AccessToken看看与前面方式获取的是不是一样的
	var Sina = new NetDimension.Weibo.Client(oauth);
	var uid = Sina.API.Account.GetUID(); //调用API中获取UID的方法
	Console.WriteLine(uid);
}

如果之前就已经成功取得并保存过AccessToken实例化OAuth之后无需再进行授权操作即可直接实例化操作类Client并进行API调用。

var oauth = new NetDimension.Weibo.OAuth("<AppKey>", "<AppSecret>", "<AccessToken>","<RefreshToken>");
NetDimension.Weibo.Client Sina = null; 
if(oauth.VerifierAccessToken() == TokenResult.Success)//验证AccessToken是否有效
{
	Sina = new NetDimension.Weibo.Client(OAuth);
	var uid = Sina.API.Account.GetUID(); //调用API中获取UID的方法
	Console.WriteLine(uid);
}

##站内应用授权方式

由于站内应用于传统网页应用有所不同,用户不需要调用GetAuthorizeUrl方法来获得授权地址。新浪在页面框架内调用你的网站页面,因此父框架提供了应用授权弹出层的代码。具体请参考官方站内应用文档中的《调用应用授权弹层》章节。

下面是站内应用的授权方式代码片段:

html

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
	<title>站内应用Demo示例</title>
	<script type="text/javascript" src="http://tjs.sjs.sinajs.cn/t35/apps/opent/js/frames/client.js" language="JavaScript"></script>
	<script type="text/javascript">
		//弹出授权弹层:
		function authLoad()
		{
			App.AuthDialog.show({
				client_id: '<%=AppKey%>',    //必选,appkey
				redirect_uri: '<%=CallbackUrl%>',     //必选,授权后的回调地址,例如:http://apps.weibo.com/giftabc
				height:10
			});
		}
	</script>
	<style type="text/css">
	#authDiv
	{
		position:absolute !important;	
	}
	</style>
</head>
<body>
	<form id="form1" runat="server">
	<h1>新浪微博开放平台API for .Net SDK</h1>
	<h2>站内应用调用示例</h2>
	<p>当前应用的授权状态为:<asp:Literal Text="未授权" ID="lblAuthStatus" runat="server" /> <asp:HyperLink ID="lnkAuth" runat="server" NavigateUrl="javascript:authLoad();" Text="授权" Visible="False" /></p>
	<p>
		<asp:Button Text="调用API" runat="server" ID="btnInvoke" Enabled="false" onclick="btnInvoke_Click" />
	</p>
	<fieldset>
		<legend>调用结果</legend>
		<asp:TextBox runat="server" ID="txtResult" TextMode="MultiLine" Width="95%" Height="300" ReadOnly="true" />
	</fieldset>
	</form>
</body>
</html>

CodeBehind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using NetDimension.Weibo;

public partial class _Default : System.Web.UI.Page
{


	public const string AppKey = "733291096"; //请自行设置AppKey
	public const string AppSecret = "23fdfac5e972b9ccf79e67498cb4ace6"; //请自行设置AppSecret
	public const string CallbackUrl = "http://apps.weibo.com/sdkinternal"; //请自行设置回调地址,一般这里不用填应用实际地址,填站内应用地址也是可以的

	protected void Page_Load(object sender, EventArgs e)
	{
		if (!IsPostBack)
		{
			var sign = Request["signed_request"];

			if (string.IsNullOrEmpty(sign))
			{
				txtResult.Text = "请从站内应用地址访问本页面。";	//如果signed_request为空则说明不是从站内应用页面来调用的,结束DEMO的执行。
				return;
			}

			var oauth = new OAuth(AppKey, AppSecret, CallbackUrl);

			var token = oauth.GetAccessTokenBySignedRequest(sign); //用主框架POST过来的SignedRequest来获取AccessToken

			if (token == null || oauth.VerifierAccessToken() != TokenResult.Success)
			{
				//token为null则说明用户没有授权或者用户在取消了授权,这时显示授权按钮
				lblAuthStatus.Text =  txtResult.Text = "未授权";
				lnkAuth.Visible = true;
				btnInvoke.Enabled = false;
			}
			else
			{
				//授权成功了
				lblAuthStatus.Text=  txtResult.Text = "已授权";
				lnkAuth.Visible = false;
				btnInvoke.Enabled = true;

				//把AccessToken存在Session里备用
				Session["Token"] = token.Token;
			}
		}
		else
		{ 
			
		}



	}
	protected void btnInvoke_Click(object sender, EventArgs e)
	{
		if (Session["Token"] != null)
		{
			string token = (string)Session["Token"];
			var oauth = new OAuth(AppKey, AppSecret, token, "");
			var sina = new Client(oauth);

			var userInfo = sina.API.Dynamic.Users.Show(uid: sina.API.Entity.Account.GetUID());

			txtResult.Text = userInfo.ToString();
		}
	}
}

##针对.Net 4.0环境下调用API接口的特别说明

在.Net 4.0版的SDK中,调用API接口的返回值有动态类型(dynamic)和实体类(class)两种形式,因此在调用API的时候也与上面的例子中给出的示例稍有不同。

以获得用户的UID接口为例

//使用实体类为返回类型的调用,返回了string型。调用其他接口将会返回对应的实体类型,例如调用Status.Show接口,则返回NetDimension.Weibo.Entities.status.Entity类型。大家也看到了,这个实体类的命名空间相当长,所以使用一个支持var关键字的VS环境会使得开发变得轻松而优雅。VS2005什么的,仍了吧。
string uid = Sina.API.Entity.GetUID();
Console.WriteLine(uid); //打印获得的UID

//使用动态类型为返回类型的调用,返回dynamic类型。其结构与官方文档中接口返回json值一致。例如:http://open.weibo.com/wiki/2/account/get_uid
dynamic json = Sina.API.Dynamic.GetUID();
Console.WriteLine(json.uid); //打印获得的UID

与其他版本相比,.Net4.0的调用方式与其他版本实质上是保持一致的。唯一不同的是API命名空间下面还包含有一层Dynamic命名空间和Entity命名空间。之后的接口调用方式就是相同的了,参数也是一样的。

在项目实践中,灵活地使用两种返回类型,必然能使项目更加高效和优雅。

###关于异步调用

SDK目前已经提供了异步调用的方法,但是之前已经封装了N多API,要让每个方法都重写一次异步调用的代码显然不靠谱,好吧,我承认是我懒。最终经过几个发现版本之后还是找到了解决异步调用问题的方法。

理论其实很简单,一个泛型方法,提供返回值的类型,然后带有两个委托类型的参数,一个是调用逻辑的委托,一个是异步完成后的回调。

核心代码

public void AsyncInvoke<T>(AsyncInvokeDelegate<T> invoker, AsyncCallbackDelegate<T> callback)
{
	ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
	{
		AsyncCallback<T> result;
		try
		{
			T invoke = invoker();
			result = new AsyncCallback<T>(invoke);
			callback(result);

		}
		catch (Exception ex)
		{
			result = new AsyncCallback<T>(ex, false);
			callback(result);
		}

	}));

}

上述代码也没有什么高端之处,很简单的一段逻辑。再来看看示例代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetDimension.Weibo;

namespace WeiboSDKTestConsole
{
	class Program
	{
		static void Main(string[] args)
		{
			var oauth = new OAuth("<appkey>", "<appsecret>", "<回调地址>");
			oauth.ClientLogin("<微博帐号>", "<微博密码>"); //模拟登录下,没啥好说的,你也可以改成标准登录。
			var Sina = new Client(oauth);

			Console.WriteLine("开始发送异步请求...");

			//例子1:异步获取用户的ID
			//demo的运行环境是.net 4.0,下面展示的这种方法在2.0及以上版本环境下有效,3.0以上可以用lambda表达式来简化delegate的蛋疼写法,请看下面的例子。
			Sina.AsyncInvoke<string>(
				//第一个代理中编写调用API接口的相关逻辑
			delegate()
			{
				Console.WriteLine("发送请求来获得用户ID...");
				System.Threading.Thread.Sleep(8000); //等待8秒
				return Sina.API.Entity.Account.GetUID();
			},
				//第二个代理为回调函数,异步完成后将自动调用这个函数来处理结果。
			delegate(AsyncCallback<string> callback)
			{
				if (callback.IsSuccess)
				{
					Console.WriteLine("获取用户ID成功,ID:{0}", callback.Data);
				}
				else
				{
					Console.WriteLine("获取用户ID失败,异常:{0}", callback.Error);
				}
			}
			 );

			//列子2:获取公共微博列表
			//2.0以上用lambda来写,方便不是一点点
			Sina.AsyncInvoke<NetDimension.Weibo.Entities.status.Collection>(() =>
			{
				//获取微博,接口调用,返回值是个NetDimension.Weibo.Entities.status.Collection,所以泛型T为NetDimension.Weibo.Entities.status.Collection
				Console.WriteLine("发送请求来获得公共微博列表...");
				return Sina.API.Entity.Statuses.PublicTimeline();
			}, (callback) =>
			{
				if (callback.IsSuccess)
				{
					//异步完成后处理结果,result就是返回的结果,类型就是泛型所指定的NetDimension.Weibo.Entities.status.Collection
					Console.WriteLine("获得公共微博列表成功,现在公共频道发微博的人都是他们:");
					foreach (var status in callback.Data.Statuses)
					{
						if (status.User != null)
							Console.Write(status.User.ScreenName + " ");//打印公共微博发起人的姓名
					}
					Console.WriteLine();
				}
				else
				{
					Console.WriteLine("获取用户ID失败,异常:{0}", callback.Error);
				}

			});


			Console.WriteLine("已发送所有异步请求。等待异步执行完成...");

			Console.ReadKey(); //阻塞,等待异步调用执行完成

		}

	}
}
Clone this wiki locally