[转载]蛙蛙推荐:用.net 4.0构建新浪微博开发平台应用

mikel阅读(878)

[转载]蛙蛙推荐:用.net 4.0构建新浪微博开发平台应用 – 蛙蛙池塘 – 博客园.

摘要:现在很多互联网应用都推出了开放平台,开心人人新浪淘宝豆瓣腾讯,还有飞信也即将推出开放平台,大多数开发平台都会用OAuth认证,并提供返回json数据的Rest接口,用.NET 4.0的新特性来开发这些平台的应用有着天然的优势,一起来看看。

认证

要想使用开发平台的数据和接口,第一步肯定是登录和认证,OAuth被越来越多的开放平台所认可和使用,TerryLee已经介绍过在.NET里如何实现OAuth认证,不过是针对豆瓣平台的一些示例代码,新浪微博的OAuth认证有一些不同的地方,一会儿我会标识出来。sarlmolapple为新浪提供了新浪微博开放平台的c#版本SDK,但没有完全对新浪微博的所有接口进行支持。因此我借鉴了两位的代码写了个针对新浪微博的精简版的OAuth认证,因为简单,如果大家想开发其它开放平台的应用,也可以很快比猫画虎做出来。

首先还是要下载别人写好的OAuthBase.cs文 件,然后继承该类写一些自定义的逻辑,后来发现只通过子类来实现自定义逻辑还不好使,所以迫不得已还是修改了OAuthBase.cs类,因为新浪微博开 放平台要求生成OAuth签名时,多了一个Verifier参数,所以在生成basestring时(GenerateSignatureBase方法) 要加上这个参数。

//NOTE:add by onlytiancai@gmail.com 兼容sina登录,参考了http://code.google.com/p/opensinaapi/
if (!string.IsNullOrEmpty(Verifier) && httpMethod == "GET")
{
parameters.Add(new QueryParameter(oAauthVerifier, Verifier));
}

准备一下OAuth认证的配置项,这些配置项大家可以在数据库里配置或者写个自定义配置节在Web.config里配置,为了简单,我就先写死了,如下:

public class OAuthConfig
{
public static OAuthConfig Instance = new OAuthConfig();
public OAuthConfig()
{
RequestTokenUri = "http://api.t.sina.com.cn/oauth/request_token";
AuthorizeUri = "http://api.t.sina.com.cn/oauth/authorize";
AccessTokenUri = "http://api.t.sina.com.cn/oauth/access_token";
ApiKey = "xxxx"; //在新浪微博开放平台申请
ApiKeySecret = "xxxxxxxxxxxxxxxxxx";//在新浪微博开放平台申请
}
public string RequestTokenUri { get; set; }

public string ApiKey { get; set; }

public string ApiKeySecret { get; set; }

public string AuthorizeUri { get; set; }

public string AccessTokenUri { get; set; }
}

请求open api接口时一般要拼写PostData格式的数据,而PostData的格式是类似”?p1=a&p2=b&p3=c”,这种格式,要手动拼写这样格式的字符串很麻烦,所以我们想要一种优雅的方式,比如:

get_request(new {p1="a", p2="b", p3="c"})

这个参数是一个C# 3.5的匿名类,然后在get_request方法里可以通过反射获取到属性名和值,构建成PostData格式,但这样做性能会稍差一些,我们可以用另外一种相近的格式,如下:

get_request(new Pairs { { "p1", "a" }, {"p2", "b"}, "p3", "c" } )

这里的参数是一个Pairs类,后面的大括号套着大括号是.net 3.5的集合初始化语法,这个Pairs是我在(Using C# 3.0 Anonymous Types as Dictionaries )这篇博客的评论里看到的,我略微修改了一下,如下:

public class Pairs : List>
{
public void Add(String key, String value)
{
Add(new KeyValuePair(key, value));
}

public string ToPostData(Func valueHandler = null)
{
StringBuilder sb = new StringBuilder();
foreach (var pair in this)
{
if (sb.Length > 0)
sb.Append("&");
sb.AppendFormat("{0}={1}", pair.Key, valueHandler == null
? pair.Value : valueHandler(pair.Value));
}
return sb.ToString();
}
}

我只增加了一个ToPostData的方法,其中有一个可选的参数用来在拼接PostData时对参数值进行处理,可选参宿是.net 4.0提供的机制,如果不提供这个参数,我就按原文拼写参数值

我继承OAuthBase写了一个OAuthHelper类,其中OAuthRequest方法用来发送一个OAuth请求,如下:

public string OAuthRequest(string uri, Pairs data = null, string method = "GET")
{
//1、准备获取签名所需参数
string nonce = GenerateNonce();
string timeStamp = GenerateTimeStamp();
if (data == null)
data = new Pairs();
data.Add("source", OAuthConfig.Instance.ApiKey); //添加默认的source参数
uri += uri.IndexOf("?") > 0 ? "&" : "?";
uri += data.ToPostData(str => UrlEncode(str)); //防止参数里有",%,="等字符

//2、获取签名
string normalizeUrl, normalizedRequestParameters;
string sig = GenerateSignature(
new Uri(uri),
OAuthConfig.Instance.ApiKey,
OAuthConfig.Instance.ApiKeySecret,
Token,
TokenSecret,
method,
timeStamp,
nonce,
OAuthBase.SignatureTypes.HMACSHA1,
out normalizeUrl,
out normalizedRequestParameters);
normalizedRequestParameters = normalizedRequestParameters + "&"
+ OAuthSignatureKey + "=" + HttpUtility.UrlEncode(sig);

//3、发送WEB请求并接受数据
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
method == "POST" ? normalizeUrl : normalizeUrl + "?" + normalizedRequestParameters);
request.Method = method;
if (method == "POST")
{
using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))
{
sw.Write(normalizedRequestParameters);
}
}

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(request.GetResponse()
.GetResponseStream(), System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}

具体步骤我都做了注释,其中 GenerateNonce,GenerateTimeStamp,UrlEncode,GenerateSignature都是父类提供的方法,直接调 用即可,根据名字也很容易想出它的功能,如果你做的不是新浪微博开放平台的应用,这里可能要相应的做一些小改动。

然后是进行OAuth的三步认证,第一步获取RequestToken,第二步让用户进行授权,一般情况下会提示用户登录新浪微博或者提示用户授权或拒绝授权你的应用访问用户的新浪微博数据,第三步就是拿到AccessToken去访问受限的资源,具体过程大家可以看这里。有了上面我们写的方法,这三步就很简单了。

///
/// 登录第一步:获取RequestToken
///
public void GetRequestToken()
{
string response = OAuthRequest(OAuthConfig.Instance.RequestTokenUri);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs[OAuthTokenKey] != null)
{
this.Token = qs[OAuthTokenKey];
this.TokenSecret = qs[OAuthTokenSecretKey];
}
}
}

///
/// 登录第二部:Response.Redirect到这个页面,提示用户授权
///
///
用户认证成功后返回的地址 ///
public string GetAuthorizeUri(string callbackUri)
{
return string.Format("{0}?oauth_token={1}&&oauth_callback={2}",
OAuthConfig.Instance.AuthorizeUri,
this.Token, callbackUri);
}

///
/// 登录第三部:获取AccessToken,成功登录
///
public void GetAccessToken()
{
string response = OAuthRequest(OAuthConfig.Instance.AccessTokenUri);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs[OAuthTokenKey] != null)
{
this.Token = qs[OAuthTokenKey];
this.TokenSecret = qs[OAuthTokenSecretKey];
}
}
}

其中Token和TokenSecret是OAuthHelper的两个string类型成员。

获取JSON数据

一般开放平台的接口可以返回xml格式或JSON格式的数据,如果解析XML数据会很不通用,每一个接口需要写一个方法,而返回json的 话.NET 4.0提供的JavaScriptSerializer可以对json数据进行序列化和反序列化,json格式的数据可以反序列化成 Dictionary<string, object>类型或其类型的数组,其中object又是一个Dictionary<string, object>,但我们对Dictionary的操作会很麻烦,我们想办法吧它转换成一个C# 4.0的dynamic类型,这里有篇帖子(Turning JSON into a ExpandoObject )介绍了如何去做,我在此基础上改动了一下,并提供了一个直接把open api返回的数据转换成ExpandoObject的方法,如下。

///
/// 发送OAuth请求,并把返回的json结果转换成dynamic类型
///
///
请求地址,请确保返回json数据 ///
请求数据 ///
HttpMethod ///
public ExpandoObject OAuthRequestDynamic(string uri, Pairs data = null, string method = "GET")
{
string result = OAuthRequest(uri, data, method);
if (result == null)
return null;
return Expando(result);
}

public static ExpandoObject Expando(string json)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
object obj = serializer.DeserializeObject(json);
if (obj is ICollection)
return Expando(new Dictionary() { { "arr", obj } });
else
return Expando((Dictionary)obj);
}

//http://coderjournal.com/2010/07/turning-json-into-a-expandoobject/
private static ExpandoObject Expando(IDictionary dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary)expando;

foreach (var item in dictionary)
{
bool alreadyProcessed = false;

if (item.Value is IDictionary)
{
expandoDic.Add(item.Key, Expando((IDictionary)item.Value));
alreadyProcessed = true;
}
else if (item.Value is ICollection)
{
var itemList = new List<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><embed type="application/x-shockwave-flash" width="100" height="100"> </embed></object>

if (itemList.Count &gt; 0)
{
expandoDic.Add(item.Key, itemList);
alreadyProcessed = true;
}
}
if (!alreadyProcessed)
expandoDic.Add(item);
}

return expando;
}

这下可好了,访问opan api,直接返回的就是带类型的了,省了解析的工序了,和Python差不多,直接写出成员就行。

开发第一个应用

去新浪微博开放平台注册一个账户,得到app key和app key secret,然后就可以开发测试应用了,新建一个Default.aspx页,摆放如下控件。

<div><img src="&lt;%# Eval(" alt="" />" alt="" /&gt;
<strong>&lt;%# Eval("user.name") %&gt;:</strong>&lt;%# Eval("text")%&gt;(&lt;%# Eval("created_at")%&gt;)

</div>

控件的功能根据名字可以推测出来,先看登录

protected void btnLogin_Click(object sender, EventArgs e)
{
OAuthHelper oauth = new OAuthHelper();
oauth.GetRequestToken();
Session["oauth_token"] = oauth.Token;
Session["oauth_token_secret"] = oauth.TokenSecret;
string url = oauth.GetAuthorizeUri("http://localhost:1812/");
Response.Redirect(url);
}

先获取RequestToken,然后获取用户认证页地址,重定向过去,提示用户登录,用户登录完了之后会返回到calback uri,这里填写是本页,新浪会在返回的页面上提供oauth_verifier参数,如果有这个参数就说明是用户登录成功返回的,所以我们要在 Page_Load里做一些处理,困了,就不写那么多说明了,大家看看,大多都是借鉴了sarlmolapple的示例代码。

protected void Page_Load(object sender, EventArgs e)
{
Session[Guid.NewGuid().ToString()] = 1; //生成cookie里的sessionid,防止Redirect回来丢失Session
if (!Page.IsPostBack)
{
OAuthHelper oauth = new OAuthHelper();
if (Request["oauth_verifier"] != null)
{
oauth.Token = Session["oauth_token"].ToString();
oauth.TokenSecret = Session["oauth_token_secret"].ToString();
oauth.Verifier = Request["oauth_verifier"];
oauth.GetAccessToken();
Session["oauth_token"] = oauth.Token; ;
Session["oauth_token_secret"] = oauth.TokenSecret;

Response.Redirect("/Default.aspx");
}
if (Session["oauth_token"] != null)
{
this.lblMessage.Text = "登录成功";
this.btnLogin.Visible = false;
this.btnTimeline.Visible = true;
}
else
{
this.lblMessage.Text = "未登录";
this.btnLogin.Visible = true;
this.btnTimeline.Visible = false;
}
}
}

登录成功后,我们获取public_timeline,并直接绑定在Repeater上,不做任何解析,你猜能不能用。

protected void btnTimeline_Click(object sender, EventArgs e)
{
OAuthHelper oauth = new OAuthHelper();
oauth.Token = Session["oauth_token"].ToString();
oauth.TokenSecret = Session["oauth_token_secret"].ToString();
dynamic json = oauth.OAuthRequestDynamic(
"http://api.t.sina.com.cn/statuses/public_timeline.json",
new Pairs { { "count", "5" } });
rpt1.DataSource = json.arr;
rpt1.DataBind();
}

猜对了,不能用,但是加上如下代码就能用了

protected new object Eval(string expression)
{
string[] arr = expression.Split('.');
object obj = this.Page.GetDataItem();
IDictionary items = obj as IDictionary;
if (items != null)
{
if (arr.Length == 1)
return items[arr[0]];
else if (arr.Length == 2)
return ((IDictionary)items[arr[0]])[arr[1]];
else
throw new NotSupportedException("哥,表达式too长了,不支持呀。");
}
else return DataBinder.Eval(this.Page.GetDataItem(), expression);
}

以上代码是在网上找到的一段,出处忘了,我在它的基础上修改了一下,支持了json的二级数据的绑定,可以直接在Eval里写“user.name”这样的表达式。

public_timeline返回的json样子大概是如下:

[
{
"created_at" : "Tue Nov 30 14:34:35 +0800 2010",
"text" : "吃力不讨好的事情我是坚决不会再做了,RI你个仙人!发飙~~~~我只想说档次和素质在那里去了,
你也就只能在这种地方混!",
"truncated" : false,
"in_reply_to_status_id" : "",
"annotations" :
[

],
"in_reply_to_screen_name" : "",
"geo" : null,
"user" :
{
"name" : "习惯寂寞吗",
"domain" : "",
"geo_enabled" : true,
"followers_count" : 5,
"statuses_count" : 61,
"favourites_count" : 0,
"city" : "1",
"description" : "",
"verified" : false,
"id" : 1676792942,
"gender" : "f",
"friends_count" : 26,
"screen_name" : "习惯寂寞吗",
"allow_all_act_msg" : false,
"following" : false,
"url" : "http://1",
"profile_image_url" : "http://tp3.sinaimg.cn/1676792942/50/1284648784",
"created_at" : "Wed Dec 30 00:00:00 +0800 2009",
"province" : "51",
"location" : "四川 成都"
},
"favorited" : false,
"in_reply_to_user_id" : "",
"id" : 3978753419,
"source" : "<a rel="\&quot;nofollow\&quot;" href="\">新浪微博</a>"
},
...
]

最后来张图吧

[原创]修改SQLServer2008的内置账户方法

mikel阅读(1262)

刚装的SQLServer2008选择的内置账户是Network Services ,可是在附加数据库的时候,提示无权限访问文件,去google了一下发现时内置账户的问题,于是更改了内置账户为Local Services 结果 SQL Server服务没办法启动了!

于是去控制面板->管理工具->服务中将SQL Server的账户改为内置账户,重启服务,附加数据库成功!

[转载]Asp.NET MVC Widget开发 - Html.Widget扩展方法

mikel阅读(971)

[转载]Asp.NET MVC Widget开发 – Html.Widget扩展方法 – Creative dream – 博客园.

ASP.NET开发博客类系统,我们经常都会用到Widget,像在线好友、最近访问好友、最新留言等,关于ASP.NET MVC与Asp.NET视图的差异,这里不再说了,大家可去查一下,接下来我以“我的好友”列表来要介绍在Asp.NET MVC实现这一功能以及结构设计。

  • 开发工具:VS 2010 EN
  • 开发语言:Visual C#
  • ASP.NET MVC 3
  1. ASP.NET MVC Widget – 设计
  2. Asp.NET MVC Widget – Controller控制器
  3. Asp.NET MVC Widget – ViewEngine
  4. Asp.NET MVC Widget – Mobile支持
  5. Asp.NET MVC Widget – Html.Widget扩展方法

前4篇文章中,已实现Widget具体开发,并支持当前流行的手机客户端,以及如何在页面中使用:

@{Html.RenderAction(“Friends”, “Widget”); }

每次这样总感觉有些烦琐,而我们想要的只是指定Widget名称就行了:

@Html.Widget(“Friends”)

实现方法是很简单,扩展HtmlHelper方法

具体代码:

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

namespace System.Web.Mvc.Html
{
public static class WidgetExtensions
{
public static MvcHtmlString Widget(this HtmlHelper htmlHelper, string widget)
{
htmlHelper.RenderAction(widget, "Widget");
return MvcHtmlString.Empty;
}
}
}

部署和安装SQL Server 2008数据库(二)

mikel阅读(1020)

SQL Server 2008SQL Server 2005安装过程有许多不同,比如网络环境的问题、账户的问题、安装向导的问题等等。目前很多公司的服务器从Windows Server 2003也逐渐升级升级到了2008,数据库升级到SQL Server 2008 也在所难免,所以平时有很多朋友在问部署SQL Server 2008过程中的问题,笔者在这里进行详细总结。
SQL Server 2008 安装的环境如下:
1, 工作组环境下的服务器
2, 域环境下的域控制器
3, 域环境下的成员服务器
4, 群集环境
事实上从开发和应用的角度讲,很多devoloper很少接触基于域控制器的开发应用,所以他们的应用多半都跑在工作环境下的服务器上,IIS中会发布很多网站,服务器本身会承载数据库的角色等,此时会涉及到在工作组环境下安装SQL Server 2008。但微软平台企业级应用开发很少有域不参与的地方,比如微软的CRMSharePointuc等产品的二次开发、.NET平台为了适应企业环境和组织架构在域模式下的应用开发等,此时会涉及到在域控制器、成员服务器和群集中安装SQL Server 2008
无论是哪一种环境下安装SQL Server 2008,都会碰到为每个SQL Server 2008服务配置账户的问题。安装SQL Server 2008时会用的账户如下:
1, 本地用户帐户
2, 域用户帐户
3, 内置系统帐户
l Network Service 帐户(网络服务)
l Local Service 帐户(本地服务)
l Local System 帐户(本地系统)
本地用户帐户
工作组环境,如果计算机不在域中,则建议使用不具有 Windows 管理员权限的本地用户帐户。
域用户帐户
如果服务必须与网络服务进行交互,则访问类似于文件共享的域资源;如果服务使用到运行 SQL Server 的其他计算机的链接服务器连接,则可以使用具有最低特权的域帐户。许多服务器到服务器的活动只能使用域用户帐户来执行。此帐户应由域管理员在域环境内预先创建。
Local Service 帐户:
Local Service 帐户是一个内置帐户,与 Users 组的成员具有相同级别的资源和对象访问权限。如果有个别服务或进程的安全性受到威胁,则此有限访问权限有助于保护系统的安全性。以 Local Service 帐户身份运行的服务将以一个没有凭据的 Null 会话形式访问网络资源。请注意,SQL Server SQL Server 代理服务不支持 Local Service 帐户。该帐户的实际名称为“NT AUTHORITY\LOCAL SERVICE”
Network Service 帐户:
Network Service 帐户是一个内置帐户,比 Users 组的成员拥有更多的对资源和对象的访问权限。以 Network Service 帐户身份运行的服务将使用计算机帐户的凭据访问网络资源。该帐户的实际名称为“NT AUTHORITY\NETWORK SERVICE”
Local System 帐户:
Local System 是一个具有高特权的内置帐户。它对本地系统有许多权限并作为网络上的计算机。该帐户的实际名称为“NT AUTHORITY\SYSTEM”
如果是在工作组环境下安装SQL Server 2008:
使用的账户是本地用户帐户,内置账户(网络服务账户、本地系统账户等)。
在域环境上(涵盖成员服务器)安装 SQL Server 2008:
出于安全方面的考虑,Microsoft 建议不要将 SQL Server 2008 安装在域控制器上。 SQL Server 安装程序不会阻止在作为域控制器的计算机上进行安装,但存在以下限制:
Windows Server 2003 上,SQL Server 服务可在域帐户或本地系统帐户下运行。
在域控制器上,无法在本地服务帐户或网络服务帐户下运行 SQL Server 服务。此时用的账户一般是域账户和本地系统账户。
SQL Server 安装到计算机上之后,无法将此计算机从域成员更改为域控制器。 必须先卸载 SQL Server,然后才能将主机计算机更改为域控制器。
SQL Server 安装到计算机上之后,无法将此计算机从域控制器更改为域成员。 必须先卸载 SQL Server,然后才能将主机计算机更改为域成员。
在群集节点用作域控制器的情况下,不支持 SQL Server 故障转移群集实例。
SQL Server 安装程序不能在只读域控制器上创建安全组或设置 SQL Server 服务帐户。 在这种情况下,安装将失败。
SQL Server 2008 安装程序安装该产品所需的以下软件组件:
l .NET Framework 3.5 SP1
l SQL Server Native Client
l SQL Server 安装程序支持文件
l SQL Server 安装程序要求使用 Microsoft Windows Installer 4.5 或更高版本
如果安装SQL Server 2008之前已经装了Visual Studio 2008,安装时出现错误,请先安装Visual Studio 2008 SP1
SQL Server 2008安装SSRS服务时,不再像SQL Server 2005必须要先安装IIS,安装SQL Server 2008不在需要IIS的支持。
下面我们以域环境下的域控制器为例安装SQL Server 2008
步骤1:启动安装程序后,如下图:

步骤2:在SQL Server 2008装中心的计划里面,可以用系统配置检查器检测服务器是否具备条件安装SQL Server 2008系统配置检查器在安装过程中会被安装程序多次调用。还可以通过在早期SQL Server版本的服务器上安装安装升级顾问来自动帮助你分析升级需要的成本和能升级什么服务,安装完安装升级顾问后,可以连接到早期版本的实例进行分析。这里单击系统配置检查器来检测系统。

系统配置检查器检测的情况如下图:

步骤3:单击安装后,在这里我们可以选择全新安装SQL Server 2008,安装群集,升级安装等。这里单击全新SQL Server独立安装或向现有安装添加功能,如下图:

步骤4:可以使用180天的企业评估版等,也可以输入你购买的产品密钥进行授权安装。

输入产品密钥:

如果你输入的是企业版的密钥就会看到企业版的许可条款,如果输入的是开发版的密钥就会看到开发版的许可条款:

步骤5:安装程序支持文件,如下图:

步骤6:安装程序支持规则,如下图:

步骤7:功能选择,根据需要选择想要安装的功能,如下图:

步骤8:可以配置成默认实例或者命名实例,如果默认实例还没被以前安装的实例占用,则可以使用默认实例。如下图:

可以修改命名实例的实例ID

我们这里使用默认实例进行安装:

步骤9:磁盘空间要求,如下图:

步骤10:配置各个服务使用的账户,如下图:

步骤11:配置排序规则,默认即可,如下图:

步骤12:选中“混合模式”,指定sa账户的密码,并指定SQL Server管理员,通过单击“添加当前用户”选择当前账户即可,也可以选择其他的账户。如下图:

步骤13:配置数据库引擎的数据目录的路径,根据需求修改,可以把各个目录的路径配置到不同的磁盘,减小I/O的负载。这里采用默认。如下图:

步骤14:可以启用FilesStream特性,这里默认没有启用,如下图:

步骤15:为Analysis Services服务指定管理员,这里选择当前用户,如下图:

步骤16:配置Analysis Services服务的数据目录,这里采用默认配置,如下图:

步骤17Reporting Serivices配置,默认即可,如下图:

步骤18:错误和使用报告,如下图
步骤19:检测安装规则,看是否能顺利安装,如下图:
步骤20:准备安装,如下图:
步骤21:安装进度,慢慢等吧 ,^_^。如下图:
步骤22:各个功能都安装完成,如下图:
步骤23:安装完成,如下图:
本节结束。

本文出自 “李涛的技术专栏” 博客,请务必保留此出处http://terryli.blog.51cto.com/704315/439573

[转载]使用 jQuery dataTables - 2 四种数据来源

mikel阅读(1025)

[转载]使用 jQuery dataTables – 2 四种数据来源 – haogj – 博客园.

四种数据来源

对于 dataTables 来说,支持四种表格数据来源。

最为基本的就是来源于网页,网页被浏览器解析为 DOM 对象,在 dataTables 中称为  DOM 来源。


$(document).ready(function() {
	$('#example').dataTable();
} );

第二种数据来源为数组, JavaScript 中的数组,通过在初始化对象中传递一个名为 aaData 的数组,同样可以提供表格数据,前缀 aa 说明这是一个数组的数组,外层的数组表示表格的行,每一行同样是一个数组。


$(document).ready(function() {
	$('#demo').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"></table>' );
	$('#example').dataTable( {
		"aaData": [
			/* Reduced data set */
			[ "Trident", "Internet Explorer 4.0", "Win 95+", 4, "X" ],
			[ "Trident", "Internet Explorer 5.0", "Win 95+", 5, "C" ],
			[ "Trident", "Internet Explorer 5.5", "Win 95+", 5.5, "A" ],
			[ "Trident", "Internet Explorer 6.0", "Win 98+", 6, "A" ],
			[ "Trident", "Internet Explorer 7.0", "Win XP SP2+", 7, "A" ],
			[ "Gecko", "Firefox 1.5", "Win 98+ / OSX.2+", 1.8, "A" ],
			[ "Gecko", "Firefox 2", "Win 98+ / OSX.2+", 1.8, "A" ],
			[ "Gecko", "Firefox 3", "Win 2k+ / OSX.3+", 1.9, "A" ],
			[ "Webkit", "Safari 1.2", "OSX.3", 125.5, "A" ],
			[ "Webkit", "Safari 1.3", "OSX.3", 312.8, "A" ],
			[ "Webkit", "Safari 2.0", "OSX.4+", 419.3, "A" ],
			[ "Webkit", "Safari 3.0", "OSX.4+", 522.1, "A" ]
		],
		"aoColumns": [
			{ "sTitle": "Engine" },
			{ "sTitle": "Browser" },
			{ "sTitle": "Platform" },
			{ "sTitle": "Version", "sClass": "center" },
			{
				"sTitle": "Grade",
				"sClass": "center",
				"fnRender": function(obj) {
					var sReturn = obj.aData[ obj.iDataColumn ];
					if ( sReturn == "A" ) {
						sReturn = "<b>A</b>";
					}
					return sReturn;
				}
			}
		]
	} );
} );

aoColumns 参数用来定义表格的列,这是一个数组,其中的每一个对象用来定义一列。

对于每一个列对象:

sTitle 定义列的标题

sClass 定义列的样式

fnRender 函数用来渲染列,这个函数将会传递一个参数对象,这个参数对象的 iDataColumn 属性表示当前的列索引,aData 表示当前的行数组。函数返回的结果将被填充到单元格中。

当然了,对于表示行的数组来说,长度应该是相同的。如果某一行数据缺失或者提供了过多地数据的话,就会得到一个警告。

错误的数组

第三种数据来源是 AJAX,也就是说可以向服务器发一个请求来获得数据。

在初始化参数对象中,通过 sAjaxSource 的属性传递请求的地址,bProcessing 表示是否需要显示一个工作中的提示。

在 JSON 方式返回的数据中,需要一个名为 aaData 的属性来提供实际的数据。

$(document).ready(function() {
	$('#example').dataTable( {
		"bProcessing": true,
		"sAjaxSource": '../examples_support/json_source.txt'
	} );
} );

其中 json_source.txt 就是 JSON 数据,其中定义了一个名为 aaData 的属性。这个文件可以在下载的压缩包中找到,在 examples\examples_support 文件夹中。

最后一种数据来源是服务器,对于大量的数据来说,你可能希望在服务器端完成所有的操作,分页、排序、过滤等等。dataTable 可以通过服务器完成这些功能,甚至其他的服务器,像  Google Gears 或者 Adobe Air,这样的话,dataTables 就是一个显示数据和提供操作事件的前端模块。

$(document).ready(function() {
	$('#example').dataTable( {
		"bProcessing": true,
		"bServerSide": true,
		"sAjaxSource": "../examples_support/server_processing.php"
	} );
} );

对于服务器来说,可以通过请求参数来获得当前的操作信息。

类型 名称 说明
int iDisplayStart 显示的起始索引
int iDisplayLength 显示的行数
int iColumns 显示的列数
string sSearch 全局搜索字段
boolean bEscapeRegex 全局搜索是否正则
boolean bSortable_(int) 表示一列是否在客户端被标志位可排序
boolean bSearchable_(int) 表示一列是否在客户端被标志位可搜索
string sSearch_(int) 个别列的搜索
boolean bEscapeRegex_(int) 个别列是否使用正则搜索
int iSortingCols 排序的列数
int iSortCol_(int) 被排序的列
string sSortDir_(int) 排序的方向 “desc” 或者 “asc”.
string sEcho DataTables 用来生成的信息

这篇文章介绍了在 C# 中结合 LINQ 使用 DataTables 进行服务端处理的经验 jQuery DataTables Plugin Meets C#

服务器应该返回如下的 JSON 格式数据

类型 名称 说明
int iTotalRecords 实际的行数
int iTotalDisplayRecords 过滤之后,实际的行数。
string sEcho 来自客户端 sEcho 的没有变化的复制品,
string sColumns 可选,以逗号分隔的列名,
array array mixed aaData 数组的数组,表格中的实际数据。
<pre>{
    "sEcho": 3,
    "iTotalRecords": 57,
    "iTotalDisplayRecords": 57,
    "aaData": [
        [
            "Gecko",
            "Firefox 1.0",
            "Win 98+ / OSX.2+",
            "1.7",
            "A"
        ],
        [
            "Gecko",
            "Firefox 1.5",
            "Win 98+ / OSX.2+",
            "1.8",
            "A"
        ],
        ...
    ] 
}

[转载]使用 jQuery dataTables - 1

mikel阅读(1034)

[转载]使用 jQuery dataTables – 1 – haogj – 博客园.

JQuery 的插件 dataTables 是一个优秀的表格插件,提供了针对表格的排序、浏览器分页、服务器分页、筛选、格式化等功能。dataTables 的网站上也提供了大量的演示和详细的文档进行说明,为了方便学习使用,这里一步一步进行说明。

首先,需要到 dataTables 的网站 http://www.datatables.net/ 下载这个脚本库,

目前的版本是 1.7.5,下载的压缩包中使用的 JQuery 是 1.4.4 。现在 jQuery1.5.1 已经发布,所以,这里使用最新的 jQuery 1.5.1 。

然后,在网页中先加入 jQuery 的引用,然后,加入 dataTables 的引用。

配置脚本

对于 dataTables 来说,表格必须通过 thead 和 tbody 进行说明,如下所示,

<table id="example" class="display" border="0" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th> Rendering engine</th>
<th> Browser</th>
<th> Platform(s)</th>
<th> Engine version</th>
<th> CSS grade</th>
</tr>
</thead>
<tbody>
<tr class="odd gradeX">
<td>Trident</td>
<td>Internet Explorer 4.0</td>
<td>Win 95+</td>
<td class="center">4</td>
<td class="center">X</td>
</tr>

如果没有 thead 将会报错。

表格错误

最为简单的使用方式,就是零配置的方式。

/*
* Example init
*/
$(document).ready(function(){
$('#example').dataTable();
});

表格的效果

默认效果

注意,红框表示了四个默认的设置效果,分别用来选择每页的行数,表格的过滤器,表格的信息和换页。

此时,使用了几个默认的参数设置。在 dataTables 中,参数名称的前缀用来说明参数的数据类型,很明显,b 表示布尔类型,i 表示整数类型,s 表示字符串类型。

  • bPaginate: 是否分页,默认为 true,分页
  • iDisplayLength : 每页的行数,每页默认数量:10
  • sPaginationType: 分页样式,支持两种内置方式,two_button 和 full_numbers, 默认使用 two_button。
  • bLengthChange : 是否允许用户通过一个下拉列表来选择分页后每页的行数。行数为 10,25,50,100。这个设置需要 bPaginate 支持。默认为 true。
  • bFilter: 启用或禁止数据过滤,默认为 true。 注意,如果使用过滤功能,但是希望关闭默认的过滤输入框,应使用 sDom
  • bInfo: 允许或者禁止表信息的显示,默认为 true,显示信息。

我们也可以通过传递一个初始化参数对象来改变这些设置。例如,下面的例子将每页的行数设置为 20 行。

$(function () {
$("#example").dataTable(
{
iDisplayLength: 20
}
);
});

[原创]自定义VS2008的起始页的新闻订阅RSS

mikel阅读(1117)

自定义起始页的新闻区

  1. “工具”菜单上单击“选项”
  2. 展开“环境”,然后单击“启动”
  3. “起始页新闻频道”中,输入新闻 RSS 源 URL。
  4. 单击“确定”

同时可以使用VS2008的浏览器浏览网页,这样不用再VS2008和浏览器间来回切换了,的确方便了不少

[原创]树形分类数据库表结构设计

mikel阅读(1809)

最近项目中涉及到树形结构的分类信息管理功能,最终显示格式如下:

树形结构显示效果图

最初我设计的数据库表结构如下:

ID 分类名称 上级分类ID 当前分类层次

结果添加了几个不同的顶级分类的子类后,查询出数据显示的效果如下:

顺序混乱的树形显示

顺序混乱的树形显示

“鞋”这个分类数据库中上级分类Id存储的是服装分类的ID,但是我们查询出来后,遍历显示的效果确实在汽车用品里,因为我们是按默认ID排序的,所以显示的时候根本没有层级关系,尽管数据库中存储着“当前分类层次”这个字段值,还是需要我们手工处理显示问题,要么利用SQL语句根据层级关系一级一级的读取数据返回数据,要么用JavaScript在页面一级进行表格的row操作来切换行的位置,都是很费时费力的方法,于是想到记录每一个分类的路径信息,于是修改了数据库表结构如下:

ID 分类名称 上级分类ID 当前分类层次 分类路径

这个“分类路径”是做什么用的?

首先分类路径存储的是当前分类到顶级分类的完整路径,以一级ID,二级ID,…..,当前级ID的格式存储,这有什么好处呢?

大家利用SQL按分类路径进行一下排序就知道了,是不是自然的按照层级关系读取出数据来了,读取的数据如下:

数据库表结构

数据库表结构

好了,既然表结构出来了,那么就需要考虑path数据什么时候生成,当然是插入新分类的时候生成于是有了存储过程如下:

ALTER PROCEDURE Store_GoodsCategoryCreate
	@Identifier int,
	@ParentID int,
	@Sort_Order int,
	@is_Show int,
	@grade int,
	@Cate_Level int,
	@CategoryName nvarchar(20)=NULL,
	@Keywords nvarchar(500)=NULL,
	@Cate_Desc nvarchar(MAX)=NULL,
	@Cate_Unit nvarchar(20)=NULL,
	@home_display nvarchar(20)=NULL,
	@Filter_attr nvarchar(500)=NULL,
	@Cate_Path nvarchar(500)=NULL
AS
BEGIN TRAN
	--选择ParentNode的Level+1
	SELECT @Cate_Level=Cate_Level+1 FROM Store_GoodsCategory WHERE Identifier=@ParentID
	IF @Cate_Level=0
	BEGIN
		ROLLBACK TRAN
	END
	--插入分类数据
	INSERT INTO Store_GoodsCategory(ParentID,Sort_Order,is_Show,grade,Cate_Level,CategoryName,
       Keywords,Cate_Desc,Cate_Unit,home_display,Filter_attr,Cate_Path)
	VALUES(@ParentID,@Sort_Order,@is_Show,@grade,@Cate_Level,@CategoryName,@Keywords,@Cate_Desc,
         @Cate_Unit,@home_display,@Filter_attr,@Cate_Path)
	IF(@@ERROR&gt;0)
	BEGIN
		ROLLBACK TRAN
	END
	SET @Identifier=@@IDENTITY --记录刚刚添加的ID

	--更新本节点的路径信息
	UPDATE Store_GoodsCategory
	SET
		Cate_Path=(select Cate_Path+','+Cast(@Identifier as nvarchar(20)) from Store_GoodsCategory where Identifier=@ParentID )
	WHERE
		Identifier=@Identifier

	IF(@@ERROR&gt;0)
	BEGIN
		ROLLBACK TRAN
	END

COMMIT TRAN

[转载]WPF中实现对Flash的播放及(循环)截图

mikel阅读(1176)

[转载]WPF中实现对Flash的播放及(循环)截图 – SongShu – 博客园.

要想实现Flash的播放支持,需要借助Flash自身的ActiveX控件.

而WPF作为一种展现层的技术,不能自身插入COM组件,必需借助Windows Form引入ActiveX控件.
比较标准的实现方法,可以参考以下链接:http://blogs.msdn.com/b/jijia/archive/2007/06/07/wpf-flash-activex.aspx
而本文则是介绍通过借助System.Windows.Forms下的WebBrowser实现.
但无论是那一种方法,本质上都是通过在WPF程序中引用Windows Form窗体,再在其内引入ActiveX控件.
实现对Flash的播放
首先,引入可在WPF上承载 Windows 窗体控件的元素:WindowsFormsHost,及添加对 Windows 窗体的引用.
具体的实现过程:项目引用–添加引用–选择 “WindowsFormsIntegration” 及 “System.Windows.Forms” –添加
在WPF页面分别添加这两者的引用:
XAML中的所有实现代码:
<Window x:Class="Capture.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:host="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="File Capture" Height="600" Width="800"
Unloaded="Window_Unloaded"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<host:WindowsFormsHost x:Name="host">
<forms:WebBrowser x:Name="browser"></forms:WebBrowser>
</host:WindowsFormsHost>
<Grid Background="Gray" Grid.Column="1">
<UniformGrid Rows="5" VerticalAlignment="Top">
<Button x:Name="btnOpen" Width="100" Height="30" Click="btnOpen_Click" Margin="0,10">Open File</Button>
<Button x:Name="btnCapture" Width="100" Height="30" Click="btnCapture_Click" Margin="0,10">Start Capture</Button>
<Button x:Name="btnStop" Width="100" Height="30" Click="btnStop_Click" Margin="0,10">Stop Capture</Button>
<CheckBox x:Name="cboxLoop" IsChecked="True" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="25,10,0,10">Loop Capture</CheckBox>
</UniformGrid>
</Grid>
</Grid>
</Window>

当需要把一选中的Flash文件(.swf 文件)添加进WebBrowser 中播放:
browser.Navigate(currentPath);
实现对Flash的截图
实现对Flash的截图,只要使用WebBrowser的基类WebBrowserBase里面的DrawToBitmap方法.
参数Bitmap为所绘制的位图(需初始化位图的大小),Rectangle为截取WebBrowser内容的区域(大小)
private void Capture()
{
 string fileName = System.IO.Path.GetFileNameWithoutExtension(currentPath);
string capturePath = string.Format(&quot;{0}\\Capture\\{1}&quot;, System.Environment.CurrentDirectory, fileName);

 if (!Directory.Exists(capturePath))
 {
 Directory.CreateDirectory(capturePath);
}

 Bitmap myBitmap = new Bitmap((int)host.ActualWidth, (int)host.ActualHeight);
 System.Drawing.Rectangle DrawRect = new System.Drawing.Rectangle(0, 0, (int)host.ActualWidth, (int)host.ActualHeight);
 browser.DrawToBitmap(myBitmap, DrawRect);

 string timeNow = DateTime.Now.ToString(&quot;yyyyMMddHHmmssfff&quot;);

 myBitmap.Save(string.Format(&quot;{0}\\{1}_{2}.png&quot;, capturePath, fileName, timeNow));
}

界面效果:
如上图所示,本实例实现了对Flash的循环截图,时间间隔为1秒.本部分比较简单,
通过使用System.Windows.Threading下的DispatcherTimer即可实现.具体可参考本文最后的附件代码.
实例代码下载:
1 xmlns:host="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 2 xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"

[转载]用CSS制作一个圆形放大镜

mikel阅读(1106)

[转载]用CSS制作一个圆形放大镜 – EtherDream の 原创空间 – 博客园.

话说图片放大,这是一个再容易不过的效果了。当然,今天说的可不是简简单单的在一个框里放大,而是一个圆。就像放大镜或是狙击镜那样,只有圆圈里的放大, 圈外的当然还是原来的图片。这是不是很不可思议? 当然不是。做过Flash的也许会脱口而出:套个蒙版就是了。可惜CSS不是Flash,没有那一套。我们只有从CSS里面慢慢挖掘。

先说IE,因为IE有滤镜,可以实现许多意想不到的功能。先来整理下我们的目标:
1.放大一副图片
2.只显示其中的一个圆
3.圆外是透明的

图片的缩放可以通过img元素的拉伸来实现。接着盖上一张透明像素画的实心圆,因此正好只显示出放大后中心圆圈部分。但第3步可就不对了,虽然之前加盖了 一张透明圆形的gif图片,屏幕上确实出现了一个放大过的圆形图片,但圆圈的外面却变成加盖图片的背景色了,因为这张图片是在最上层了。到此你或许在想给 其中某些元素加些透明度什么的,事实上无论给哪个层加透明度都是徒劳的。因为此时无非就两种情况:圆圈外被背景色覆盖;背景色透明的话就是一个矩形的放 大,而不是圆形。我们所希望的是:蒙版的背景色透明,并且在此位置下面的放大图也跟着透明

对于IE来说,这并非难事,因为IE有滤镜。如果你熟悉的话应该早就想到了Chroma滤镜,这是一个很重要的滤镜,因为他能把一个层里的指定颜色变成透 明色!这不正是我们期待吗。我们新建一个层,层里面分别叠上放大图片(后)和蒙版图片(前),就是为了让他们合并到这个新建层里。我们给这个新建层设置 Chroma滤镜,因为他们的子层都在此合并像素了,所以圆圈外那部分背景色透明后,取而代之的就是原图片。这就是我们最终想要的效果。

值得注意的是,Chroma滤镜在给指定的蒙版背景色透明的时候,圆圈里同样的颜色也会一起透明掉,所以要给蒙版设置一个非常少见的背景色,尽可能减少圆圈里的透明像素点

IE上面的解决方案还算简单,非IE的呢?你当然会说canvas,因为图形方面他是万能的。如果CSS上确实找不到办法,我们也只能用canvas。不 过可别忘了那些非IE的主流浏览器几乎都是支持CSS3的。CSS3虽然没有像Chroma滤镜那样的效果,但是对于本例这样的效果还是绰绰有余的:因为 我们只想要一个放大了的圆形图片,而CSS3天生就支持画圆。

CSS3支持层的圆角,例如border-radius:5px,就能给层的4个方角变为半径5px的圆角。我们不妨将其运用到极限,给一个 100*100的层设置一个border-radius:50px圆角,这时可就是一个圆滚滚的层了!层里面的内容当然不会限制在圆角里面,但层的背景图 片会。并且CSS3是支持背景图片缩放的,本例到此也就迎刃而解了。

前面关键的问题都以解决,下面就实现一个狙击瞄准器的效果,并支持滚轮缩放。为了使代码更清晰,本例分别为IE,FF及其他浏览器做了3个版本,通过Demo页面能够自动转跳。

Demo:

http://www.etherdream.com/funnyscript/zoom/Demo.html

当然,如果再改进的话我们还可以用png图片作为蒙版,带上一些渐变的透明度,就更像玻璃的材质了。(2010/12/20)