[转载]想成为优秀的技术人员你必须做到的几件事情

mikel阅读(851)

[转载]想成为优秀的技术人员你必须做到的几件事情 – 海纳百川 – 博客园.

找工作的这几天,收获颇多。思考得最多的问题可能就是对未来的一个规划。无意中看到下面几条经验,发现和自己想的也差不多,就分享出来。我要求自己做到这些,同时也希望对您也有所帮助。英文的原文是:Things you need to remember to become a successful developer

1、保持学习

一个非常重要的观点是:如果你停留在一个地方不前,并不代表你能一直呆在那里,而是代表你正在落后(不进则退)。往前进并不意味着你是就能进步 – 这至少你不会沦落到最后(付出就会有收获) 。程序员为了保持向前发展,就需要不断学习 ,我们需要的不是慢慢的往前走,而是我们要奔跑起来!下面列出这方面的几个观点:

1)、读书

2)、订阅RSS和阅读一些杂志(我觉得msdn的杂志不错)

3)、参加一些研讨会,自己准备一些简报(社区精英、博客园每月的活动等都不错)

4)、学习一切可以帮助你的东西

5)、教其他人其实也是教自己

2、给自己确定目标

如果不知道向什么方向发展,是很难有成就的。这一点关键是自己要有一个清晰地目标。这个应该是个长期的目标,然后要有一个目标的愿景。首先要把这个目标分 成一些小的任务,建立实现这些目标的路线图。你可以创建每月或每年你必须完成的一个任务列表,然后根据这个任务列表去实现。

3、生活中的每一个挑战都是一个机遇

在日常工作时,总是会遇到各种各样的问题。你可能会遇到一些程序的bug;项目经理分配的新任务;你同事请你帮助;你请别人帮助。这些都是一个一个的挑战。问题是:你如何去解决这些挑战?我的一个答案是:你必要调动你所有的激情去应对这些挑战,因为每个挑战就是一个机遇。

4、抱有积极态度

对待每一件事情都应抱着积极的态度。如果发现你犯了一个错误,请不要在意,因为没有人是不会犯错误的。你可以想象一下,有谁喜欢那种一遇到问题就抱怨的人 呢?如果你说“好吧,伙计们,我能做到的,请给我一分钟,我就会解决这个问题。”,然后笑着转过身就修改自己的错误,这样在别人眼里又是如何看待你呢?当 您解决这个问题之后,你会感觉到异常的高兴。

相信自己的方法是正确的,自己正在快速进步。千万不要老是认为自己无法达到自己的目标。

5、给自己寻找一个导师

这并不是说你需要一个人来帮助你来完成你的工作。导师可能就是比你职别高的职员。而且他的职位是你想要去争取的。如果他的职位你争取到了,你可以再选择另外一个更高的。但是你必要一直都需要有这么一个人。也可以能督促你和支持你的朋友、亲人、恋人等等。

6、让自己公众化

如何让别人知道你呢?一个最简单的办法是写博客、提问题、帮别人解决问题。起码要google知道你吧。学会在团队和项目中分享自己的知识。如果你学了新的知识,就把它分享出来!如果你没有分享,下次再用的时候,你可能就忘记了。

7、时不时的审查一下自己,确保自己的方式正确

时不时的,你需要检查你做的方法是否全正确。检查一下是否完成即将完成的目标。如果没有,赶快找原因,加紧去完成。寻找你的薄弱环节,加强它们。这听起来 很滑稽:我认识一个技术很强的开发人员,但他的打字速度却是很慢。为什么?因为他对键盘不熟悉,又不想花10-20小时进行键盘训练。兄弟,如果你会读到 此,请务必要求自己克服此类的问题。

8、保持健康身体

我 写这篇文章之前,算是“集思广益”的。我是一个年轻男子,跟我的笔记本电脑和另一台计算机工作了太长时间,我不能强迫自己做健身运动了。这个有点像磨刀不 误砍柴工。有一个故事,两个樵夫打赌砍树,一个比较强壮,另外一个比较瘦弱。强壮的人相信他会赢得,因为他没有休息,持续砍了8小时。瘦小的那位,每隔一 个小时就休息15分钟。最后瘦小的那位樵夫却赢了。他赢的秘密在于休息的时候将刀磨锋利了。你的健康就像是斧头,如果斧头钝了,你将无法为自己人生道路披 荆斩刺。

[转载]C# 4动态编程新特性与DLR剖析

mikel阅读(878)

[转载]C# 4动态编程新特性与DLR剖析 – 金旭亮 – 博客园.

拓展动态编程的新领域

——C# 4动态编程新特性与DLR剖析

===================================================

注:
很久没有发文了,贴一篇新文吧。从Word直接贴过来的,没仔细排版,诸位海涵。
有关DLR和C# 4动态特性的详细介绍,请参看本人拙著《.NET 4.0面向对象编程揭秘(应用篇)》,目前该书正处于编辑出版流程中,估计12月上市。
与此书相关的技术资源,将陆续发布于博客园与CSDN的本人博客。

金旭亮

=====================================================================================

近几年来,在TIOBE公司每个月发布的编程语言排行榜[1]中,C#总是能挤进前10名,而在近10年的编程语言排行榜中,C#总体上呈现上升的趋势。C#能取得这样的成绩,有很多因素在起作用,其中,它在语言特性上的锐意进取让人印象深刻( 1)。

1 C#各版本的创新点

2010年发布的C# 4,最大的创新点是拥有了动态编程语言的特性。

1 动态编程语言的中兴

动态编程语言并非什么新鲜事物,早在面向对象编程语言成为主流之前,人们就已经使用动态编程语言来开发了。即使在JavaC#C++等面向对象编程语言繁荣兴旺、大行于世的年代,动态编程语言也在“悄悄”地攻城掠地,占据了相当的开发领域,比如 JavaScript业已成为Web客户端事实上的主流语言。

最近这几年,动态编程语言变得日益流行,比如PythonRuby都非常活跃,使用者众多。

这里有一个问题,为什么我们需要在开发中应用动态编程语言?与C#Java这类已经非常成熟且功能强大的静态类型编程语言相比,动态编程语言有何优势?

简单地说,使用动态编程语言开发拥有以下的特性:

1)支持REPLRead-evaluate-print Loop:“读入à执行à输出”循环迭代)的开发模式,整个过程简洁明了,直指问题的核心。

举个简单的例子, 2所示为使用IronPython[2]编程计算“1+2+……+100”的屏幕截图,我们可以快速地输入一段完成累加求和的代码,然后马上就可以看到结果:

2 使用IronPython编程

如果使用C#开发就麻烦多了,您得先用Visual Studio创建一个项目,然后向其中添加一个类,在类中写一个方法完成求和的功能,再编写调用这一方法的代码,编译、排错,最后才能得到所需的结果……

很明显,对于那些短小的工作任务而言,动态编程语言所具备的这种REPL开发模式具有很大的吸引力。

2)扩展方便。用户可以随时对代码进行调整,需要什么功能直接往动态对象上“加”就是了,不要时又可以移除它们。而且这种修改可以马上生效,并不需要像C#那样必须先修改类型的定义和声明,编译之后新方法才可用。

换句话说:使用动态语言编程,不需要“重量级”的OOAD,整个开发过程迭代迅速而从不拖泥带水

3)动态编程语言的类型解析是在运行时完成的,可以省去许多不必要的类型转换代码,因此,与静态编程语相比,动态编程语言写的代码往往更紧凑,量更少。

动态编程语言主要的弱点有两个:

1)代码中的许多错误要等到运行时才能发现,而且需要特定的运行环境支持,对其进行测试不太方便,也不支持许多用于提升代码质量的各种软件工程工具,因此不太适合于开发规模较大的、包容复杂处理逻辑的应用系统。

2)与静态编程语言相比,动态编程语言编写的程序性能较低。不过随着计算机软硬件技术的不断进步,比如多核CPU的广泛应用,动态编程语言引擎和运行环境不断地优化,动态编程语言编写的程序性能在不断地提升,在特定的应用场景下,甚至可以逼近静态语言编写的程序。

2 拥抱“动态编程”特性的C# 4

为了让C#Visual Basic.NET编程语言能具备动态编程语言的特性,.NET 4.0引入了一个“DLRDynamic Language Runtime:动态语言运行时)”( 3)。

3 DLR:动态语言运行时

DLR运行于CLR之上,提供了一个动态语言的运行环境,从而允许PythonRuby等动态语言编写的程序在.NET平台上运行,同时,现有的.NET静态类型编程语言,比如C#Visual Basic,也可以利用DLR而拥有一些动态编程语言的特性。

1)使用C# 4编写动态的代码

C# 4新增了一个dynamic关键字,可以用它来编写“动态”的代码。

例如,以下代码创建了一个ExpandoObject对象(注意必须定义为dynamic):

dynamic dynamicObj = new ExpandoObject();

这一对象的奇特之处在于,我们可以随时给它增加新成员:

dynamicObj.Value = 100; //添加字段

dynamicObj.Increment = new Action(() => dynamicObj.Value++); //添加方法

这些动态添加的成员与普通的类成员用法一样:

for (int i = 0; i < 10; i++)

dynamicObj.Increment();//调用方法

Console.WriteLine(“dynamicObj.Value={0}”,dynamicObj.Value);//访问字段

ExpandoObject对象实现了IDictionary<string, object>接口,可看成是一个字典对象,所有动态添加的成员都是这个字典对象中的元素,这意味我们不仅可以添加新成员,还可以随时移除不再需要的成员:

//移除Increment方法

(dynamicObj as IDictionary<string, object>).Remove(“Increment”);

方法移除之后,再尝试访问此方法将引发RuntimeBinderException异常。

2)使用dynamic关键字简化与COM组件交互的代码

要在.NET这个“托管世界”里调用“非托管世界”中的COM组件,我们必须通过 “互操作程序集(Interop Assembly)”作为桥梁,“互操作程序集”定义了CLR类型与COM类型之间的对应关系。

只要给.NET项目添加对“互操作程序集”的引用,就可以在.NET应用程序中创建这一程序集所包容的各种类型的实例(即COM包装器对象),对这些对象的方法调用(或对其属性的存取)将会被转发给COM组件。

以调用Word为例,在C# 4.0之前您可能经常需要编写这样的代码:

Object wordapp = new Word.Application();   //创建Word对象

Object fileName = “MyDoc.docx” ;//指定Word文档

Object argu = System.Reflection.Missing.Value;

Word.Document doc = wordapp.Documents.Open(ref fileName, ref argu,

ref argu, ref argu, ref argu, ref argu, ref argu, ref argu,

ref argu, ref argu, ref argu, ref argu, ref argu, ref argu,

ref argu, ref argu);

上述对Open()方法的调用语句只能用“恐怖”一词来形容,其原因是Word组件中的Open()方法定义了太多的参数。

C#4使用dynamic关键字,配合从Visual Basic中学来的“命名参数与可选参数”这两个新语法特性,可以写出更简洁的代码:

dynamic wordapp = new Word.Application();

dynamic doc = wordapp.Documents.Open(FileName: “MyDoc.docx”);

上述代码中省去了用不着的参数,并且可以去掉参数前的ref关键字。

当上述代码运行时,DLR会使用反射技术将dynamic表达式“绑定(bind)”到COM互操作程序集中所包容的Word.Application代理对象。

3C# 4动态编程技术内幕

C#4中所定义的dynamic变量可以引用以下类型的对象:

l 传统的“静态”的CLR对象。

l COM包装器对象。前面已经介绍了这方面的内容。

l 实现了IDynamicMetaObjectProvider接口的“动态对象”,ExpandoObject就是这种类型对象的实例。

l 基于DLR实现的动态语言(比如IronRubyIronPython)所创建的对象。

C#程序员角度来看,所有这四种对象都是一样的,都可用一个dynamic变量引用之,而DLR在程序运行时动态地将方法调用和字段存取请求“绑定”到真正的对象上。

dynamic的功能是由DLR所支撑的,是C#编译器与DLR分工合作的成果。

请看以下示例代码:

dynamic d = 100;

d++;

C#编译器在处理上述代码时,它并不去检查变量d是否可以支持自增操作,而是为其创建了一个CallSite<T>对象(<>p__Site1):

private static class <Main>o__SiteContainer0 {

public static CallSite<Func<CallSite, object, object>> <>p__Site1;

}

中文MSDNCallSite<T>译为“动态(调用)站点”,它是DLR中的核心组件之一。

动态站点对象通过CallSite<T>.Create()方法创建, C#编译器会为其指定一个派生自CallSiteBinder的对象(称为“动态站点绑定对象”)作为其参数。

动态站点绑定对象是与具体语言相关的,比如IronPythonC#都有各自的动态站点绑定对象。

动态站点绑定对象的主要工作是将代码中的动态表达式(本例中为d++)转换为一棵“抽象语法树(ASTAbstract Syntax Tree)”,这棵语法树被称为“DLR Tree”,是在.NET 3.5所引入的LINQ表达式树的基础上扩充而来的,因此,有时又称其为“表达式树(Expression Tree)”

DLR在内部调用此表达式树的Compile()方法生成IL指令,得到一个可以被CLR所执行的委托(在本例中其类型就是Func<CallSite, object, object>)。

动态调用站点对象(本例中为<>p__Site1)有一个Target属性,它负责引用这一生成好的委托。

委托生成之后,动态表达式的执行就体现为委托的执行,其实参由C#编译器直接“写死”在IL代码中。

简化的代码示意如下(通过Reflector得到,为便于阅读,修改了变量名):

object d = 100;

object CS$0$0000 = d;

if (<>p__Site1 == null)

<>p__Site1 = CallSite<Func<CallSite, object, object>>.Create(……);

d = <>p__Site1.Target(<>p__Site1, CS$0$0000);

上述类型推断、方法绑定及IL代码生成的工作都是在程序运行时完成的。

4)动态代码很慢吗?

动态编程语言易学易用,代码紧凑,开发灵活,但性能则一直是它的“软肋”。为了提升性能,DLR设计了一个三级缓存策略。

动态站点绑定对象会为动态调用表达式转换而成的语法树加上相应的测试条件(称为“test”),构成一个“规则(Rule)”,这个规则可以用于判断某个语法树是否可用于特定的动态调用表达式。

举个例子,请看以下这个动态表达式:

d1 + d2

如果在程序运行时d1d2都是int类型的整数,则DLR生成的规则为:

if( d1 is int && d2 is int) //测试条件

return (int)d1+(int)d2; //语法树

DLR通过检查规则中的“测试条件”,就可以知道某个动态表达式是否可以使用此规则所包容的语法树。

“规则”是DLR缓存的主要对象。

前面介绍过的动态站点对象Target属性所引用的委托是第一级缓存,它实现的处理逻辑是这样的:

//当前处理规则,属于第1级缓存

if( d1 is int && d2 is int) //测试条件

return (int)d1+(int)d2; //满足测试条件,直接返回一个表达式树

//未命中,则在第2级、第3级缓存中查找,如果找到了,用找到的结果更新第1级缓存

return site.Update(site,d1,d2);

如果3级缓存中都没有命中的规则,则此动态站点所关联的调用站点绑定对象会尝试创建一个新的规则。如果创建新规则失败,则由当前编程语言(比如C#)所提供的默认调用站点绑定对象决定如何处理,通常的作法是抛出一个异常。

当前版本的DLR2级缓存了10条规则,第3级则缓存了100条规则。

由于DLR自身设计了一个“规则”缓存系统,又充分利用了CLR所提供的JIT缓存(因为所有动态调用代码最终都会转换为CLR可以执行的IL指令,而CLR可以缓存这些代码),使得动态代码仅仅在第一次执行时性能较差,后续的连续调用其性能可以逼近静态代码。

3 C# 4与动态语言的集成

由于几乎所有的编程语言都可以使用抽象语法树来表达,因此,在理论上DLR支持无限多种编程语言间的互操作,在当前版本中,可以实现C#/Visual BasicIronPythonIronRuby的互操作,相信很快会出现其他动态编程语言的DLR实现。

一个有趣的地方是当前基于DLR实现的动态编程语言都以“Iron”开头,比如IronRubyIronPythonIronPython的设计者、DLR架构设计Jim Hugunin曾经在微软PDC 2008大会上解释说主要是为了避免起一个“Python.NET”或“Python for .NET”之类“微软味十足”的名字,才有了“IronPython”。他强调:“Iron”系列动态语言将严格遵循动态语言自身的标准和规范,尊重这些动态语言已有的历史和积累,不会引入一些仅限于.NET平台的新语言特性,并且这些语言的.NET实现保持开源。与此同时,Jim Hugunin指出 Iron”系列语言能很好地与.NET现有类库、编程语言和工具集成,并且能“嵌入”到.NET宿主程序中。

1)动态对象通讯协议

由于各种动态编程语言之间的特性相差极大,实现各语言间的互操作是个难题。为此DLR采取了一个聪明的策略,它不去尝试设计一个“通用的类型系统”(CLR就是这么干的),而是设计了一个“通用的对象通讯协议”,规定所有需要互操作的动态对象必须实现IDynamicMetaObjectProvider接口,此接口定义了一个GetMetaObject()方法,接收一个语法树对象作为参数,向外界返回一个“动态元数据(DynamicMetaObject)”对象:

DynamicMetaObject GetMetaObject(Expression parameter);

DynamicMetaObject对象向外界提供了两个重要属性:Restrictions引用一组测试条件,Expression属性则引用一个语法树。这两个属性组合起来就是可供动态站点对象缓存的“规则(Rule)”。

DLR中的“动态站点绑定对象(CallSiteBinder)”获取了DynamicMetaObject对象之后,它调用此对象所提供的各个方法创建“规则”,让“动态站点对象(CallSite<T>)”的Target属性引用它,完成动态绑定的工作。

2)动态语言集成环境

为了方便地实现静态编程语言与各种动态编程语言间的相互集成,DLR提供了一整套称为“通用寄宿(Common Hosting)”的组件,其中包容ScriptRuntimeScriptScope等类型。

下面我们以IronPython为例,介绍如何在C# 4开发的程序中集成动态编程语言代码。

首先需要创建一个ScriptRuntime对象,它是一个最顶层的对象,用于在一个.NET应用程序域中“嵌入”一个特定动态语言的运行环境:

ScriptRuntime pythonRuntime = Python.CreateRuntime();

接着需要创建一个ScriptEngine对象,它是动态语言代码的执行引擎:

ScriptEngine engine = pythonRuntime.GetEngine(“py”);

ScriptScope对象类似于C#中的命名空间,其中可以通过定义一些变量向动态代码传入数据,比如下述代码将一个C# 创建的ExpandoObject对象传给Python代码:

ScriptScope scope = pythonRuntime.CreateScope();

//C#创建动态对象

dynamic expando = new ExpandoObject();

expando.Name = “JinXuLiang”; //动态添加一个字段

//IronPython接收C#创建的Expando对象

scope.SetVariable(“ExpandoObject”, expando);

string pythonCode = “print ExpandoObject.Name”;

//IronPython引擎执行Python语句

engine.CreateScriptSourceFromString(pythonCode).Execute(scope);

上述示例代码是直接执行Python代码。在实际开发中,更常见的是直接执行Python文件中的代码,假设有一个Calculator.py文件,其中定义了一个Add函数:

def Add(a,b):

return a+b

则以下C#代码可以直接执行之:

ScriptRuntime pythonRuntime = Python.CreateRuntime();

dynamic pythonFile = pythonRuntime.UseFile(“Calculator.py”);

Console.WriteLine(pythonFile.Add(100, 200));

上述示例说明在DLR的支持之下,可以让静态编程语言使用动态语言所开发的库,反过来,基于DLR实现的动态编程语言也能使用为静态语言所设计的库,比如标准的.NET基类库。

这意味着两点:

1)我们现在可以将“静态”和“动态”编程语言组合起来,开发出一些具有高度交互性的应用程序,使用静态编程语言搭建系统框架,使用动态编程语言实现交互性,这是一个很值得注意的应用领域。

2)将来会出现一些“静态”“动态”编程语言同时适用的库,向实现“无所不在的复用”目标又前进了一步。

Visual Studio 2010为新的.NET编程语言F#提供了专门的项目模板,但没有为IronPythonIronRuby之类动态语言的开发提供支持,相信随着动态语言在.NET平台之上的应用日趋广泛,后继版本的Visual Studio会直接支持动态语言的开发。

C# 1.0~4.0所走过的路,可以很清晰地看到它的发展轨迹,得到这样的一个结论:

未来的编程语言应该是多范式的,具有高度的可组合性,在一个项目或产品中组合多个编程语言、使用多种编程范式会变得越来越普遍。

我们可以推断C#的后继版本将会在此条道路上越走越远……


[1] http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

[2] IronPython是动态语言Python基于.NET的一个实现

[转载]利用LINQ 表达式实现跨服务器查询(大数据处理)

mikel阅读(951)

[转载]利用LINQ 表达式实现跨服务器查询(大数据处理) – lilin – 博客园.

在上一篇博文《利用LINQ 表达式实现跨服务器查询》提到可以联合查询跨服务器的两张表,

实现机制是查询到的实体类Order转化为集合,如代码:List<Order> ol = oq.ToList<Order>();

在利用其集合的扩展方法Join建立两个List的对应关系。如果这时数据量比较大,

就ToList<Order>这一句就十分耗性能了。如果是企业级的数据量,这种方法是行不通的。

那么有没有更好的方法呢?我想到了一种解决方案,与大家分享:

就上篇博文的例子,比如查询到的客户,我们只知道这些客户的定单就行的,其它客户定单没必要查询。查询到的客户如下列代码:
IQueryable<Customer> cq = from c in customer

                            where c.City == "Berlin"
                            select c;
LINQ TO SQL 表达式是预定义的,也就是先不执行,当然这里查询的数据只在一页上显示就行了。如果数量大可考虑分页问题。

下面就是关键的了,如何才能查询到客户的定单,用循环定单表吗?等于全表查询并扫描,不行。
我们知道在SQL 语句中 可用 Select * From Orders Where CustomerID ='ANATR' or CustomerID ='ALFKI'来实现我们要的结果
用LINQ 查询表达式这样写:
IQueryable<Order> oq = order.Where(o => o.CustomerID == "ANATR" || o.CustomerID == "ALFKI");
这种办法查询性能并不高。

SQL 语句 Select * From Orders Where CustomerID ='ANATR' Union All Select * From Orders Where CustomerID ='ALFKI'
要比上面的方法性能高多了,合理利用上了索引。
用LINQ 查询表达式这样写:
IQueryable<Order> oq = null;
foreach (Customer c in cl)
{
string v = c.CustomerID;
if (oq == null)
{
oq = order.Where(o => o.CustomerID == v);
}
else
{
oq = oq.Concat(order.Where(o => o.CustomerID == v));
}
}
List<Order> ol = oq.ToList<Order>();

上面代码意思就是循环客户表,建立类似Where CustomerID ='ANATR' 这样的条件,再用oq.Concat方法进行联接,
LINQ To SQL 会转化为下列的SQL语名。
可用odb.Log = Console.Out;语句在屏幕上打显示出来,如下:
---------------------------------------
SELECT [t4].[OrderID], [t4].[CustomerID], [t4].[OrderDate]
FROM (
SELECT [t2].[OrderID], [t2].[CustomerID], [t2].[OrderDate]
FROM (
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[OrderDate]
FROM [Orders] AS [t0]
WHERE [t0].[CustomerID] = @p0
UNION ALL
SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[OrderDate]
FROM [Orders] AS [t1]
WHERE [t1].[CustomerID] = @p1
) AS [t2]
UNION ALL
SELECT [t3].[OrderID], [t3].[CustomerID], [t3].[OrderDate]
FROM [Orders] AS [t3]
WHERE [t3].[CustomerID] = @p2
) AS [t4]
-- @p0: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [BOLID]
-- @p1: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [FISSA]
-- @p2: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [ROMEY]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
-----------------------------
这就是我的解决方法,不对之处请指正。欢迎与大家交流。

原文件下载:App2.rar

[转载]JQuery FlexiGrid的asp.net完美解决方案-dotNetFlexGrid使用指南(一)

mikel阅读(813)

[转载]JQuery FlexiGrid的asp.net完美解决方案-dotNetFlexGrid使用指南(一) – 华磊的空间 – 博客园.

  1. 简介

JQuery FlexiGrid的ASP.NET完美解决方案

dotNetFlexGrid是一款ASP.NET原生的异步表格控件,它的前身 是JQuery FlexiGrid插件,我们重构了FlexiGrid的大部分JavaScript代码,使其工作的更有效率,BUG更少;同时将其封装为 asp.net 控件,提供了简单易用的使用方式。

dotNetFlexGrid作为一个轻量级的表格控件,同时提供了大量实用和高效的功能:

  • 控件本身是全异步的工作模式,表格数据的刷新无需重新刷新整个页面。
  • 我们提供了若干易用的客户端方法,让你的程序在添加、修改、删除表格数据时无需重新加载大量的表格数据,而仅需要更新客户端展现结果,这样使得程序的后台访问次数大大降低。
  • 我们采用了类似AjaxPro的异步回调方式,使得您不必重新为异步请求单独开发页面,通过简单的数据提供函数,您能够在同一个页面中完成所有的表格异步操作。
  • dotNetFlexGrid提供了作为一个Grid应有的全部功能,包括表格排序、列拖动、首行的复选框、斑马色、快速查询、显示和隐藏列等等。
  1. 下载和配置
  2. 下载

您可以访问http://dotnetflexgrid.codeplex.com/ 下载控件的最新版本,包括最新的控件代码、演示项目和说明文档。

同时您可以访问http://www.cnblogs.com/hualei 获取控件的最新消息和使用指导,我们将为您提供最新的全中文的指导,同时我们欢迎您提供更好的建议和指正。

  1. 配置在您的项目中

请检查您下载的文件中包含dotNetFlexGrid v1.1.rar(此处采用v1.1版进行演示),该压缩包包含dotNetFlexGrid的全部源码,请将压缩包中的所有文件解压缩到如 dotNetFlexGridControl的目录(当然,您可以设定任意的文件夹名)。

根据您的项目情况,将dotNetFlexGridControl文件夹复制到您的asp.net站点目录的任意目录下,如果您使用的是Asp.net WebApplication,请在项目中至少包含如下文件:

  • dotNetFlexGridControl\dotNetFlexGrid.ascx
  • dotNetFlexGridControl\dotNetFlexGrid.ascx.cs
  • dotNetFlexGridControl\dotNetFlexGridAsyn.aspx
  • dotNetFlexGridControl\dotNetFlexGridAsyn.aspx.cs

请打开dotNetFlexGridControl\dotNetFlexGrid.ascx.cs文件,修改如下代码为您的项目中的控件路径。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary>

/// 配置点:根据控件的实际路径配置

/// </summary>

public string ControlCurrentPath

{

get

{

// TODO:ControlCurrentPath 配置点:根据控件的实际路径配置

return “/dotNetFlexGridControl/”;

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

同时,请在您的项目中引用Newtonsoft.Json.Net20.dll(该文件在Bin目录中提供)

一切完毕,现在您可以在您的项目中正式使用dotNetFlexGrid了。

Btw:似乎的确麻烦了点,现在dotNetFlexGrid是采用Asp.net用户控件的方式进行封装的,大多数的开发中测试均是使用的 Asp.net网站项目;在发布的时候,我们考虑到易用性以及便于修改,故没有采用自定义控件的方式进行封装;不过,这样似乎对使用者更加有利。

  1. 第一个Grid

好了,我们开始我们的第一个Gird,我们将实现演示项目中的FirstGrid.aspx的效果;这个例子展示一个模拟的用户列表。

首先,打开Visual Studio 2005/2008/2010;我们需要在页面中加入控件,将您的页面切换到设计视图(在源代码中复制粘贴也是不错的主意),从解决方案资源管理器找到控 件目录下的dotNetFlexGrid.ascx,直接拖拽到页面上合适的位置,注意检查下你的控件ID(本例直接使用默认的”dotNetFlexGrid1“)。

其次,我们需要写一段代码初始化Grid,将如下代码复制到你的页面的Page_Load中。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

this.dotNetFlexGrid1.InitConfig(

new string[]{

“striped=true”,//是否显示行交替色

“selectedonclick=true”,//是否点击行自动选中checkbox

“usepager=true”,//使用分页器

“showcheckbox=true”,//显示复选框

“height=200”,//高度,可为auto或具体px值

“width=600”//宽度,可为auto或具体px值

},

new dotNetFlexGrid.FieldConfig[]{

new dotNetFlexGrid.FieldConfig(“Guid”,“编号”,60,true,dotNetFlexGrid.FieldConfigAlign.Left),

new dotNetFlexGrid.FieldConfig(“String1”,“用户名”,120,true,dotNetFlexGrid.FieldConfigAlign.Right),

new dotNetFlexGrid.FieldConfig(“String2”,“地址”,60,true,dotNetFlexGrid.FieldConfigAlign.Left),

new dotNetFlexGrid.FieldConfig(“String3”,“创建时间”,60,true,dotNetFlexGrid.FieldConfigAlign.Left)

}

);

//this.dotNetFlexGrid1.DataHandler = new dotNetFlexGrid.DataHandlerDelegate(DotNetFlexGrid1DataHandler); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

dotNetFlexGrid1.InitConfig方法提供初始化表格主控参数、列配置的功能,例子中,我们设定表格宽600px,高 200px,并绑定 “编号””用户名””地址””创建时间”四个字段,自此,其实我们的Grid已经可以使用了,浏览该页面,我们看到了如下界面:

很简单,不是吗;我们看到了一个最简单的空表格,仔细看看,如此简单的表格其实拥有了如下强大的功能:

  • 您可以点击其中一列将其拖放到合适的位置上(当然仅限表头)。
  • 您可以将鼠标移动到列的分割线上,左右拖动来调整列宽。
  • 你可以将鼠标移动到表头的列的分割线左边,点击出现的按钮来选择需要显示和隐藏的列。
  • 您可以在表格的最左边和最下边拖动表格的大小。
  • 在表头移动鼠标,你会发现字段排序的指示(虽然现在没用:-)后面我们将用到它)。
  • 显示了内置的分页器和刷新按钮,当然,现在是无用的。

接下来,我们为表格填充数据,重新转到Page_Load中,我们增加一行,并在页面中增加一个提供数据的方法。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Page_Load中

this.dotNetFlexGrid1.DataHandler = new dotNetFlexGrid.DataHandlerDelegate(DotNetFlexGrid1DataHandler); //提供数据的方法

新增方法

public dotNetFlexGrid.DataHandlerResult DotNetFlexGrid1DataHandler(dotNetFlexGrid.DataHandlerParams p)

{

dotNetFlexGrid.DataHandlerResult result = new dotNetFlexGrid.DataHandlerResult();

result.page = p.page;//设定当前返回的页号

result.total = 100;//总计的数据条数,此处用100进行模拟

result.table = dotNetFlexGrid.DemoMemoryTable(p.page * 100, p.rp);//调用演示的数据生成函数产生模拟数据

return result;

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DotNetFlexGrid1DataHandler方法接收一个类型为dotNetFlexGrid.DataHandlerParams的参数,该参数提供控件的动作所产生的所有参数,如p.page(当前请求的页号)、p.rp(当前请求所希望返回的行数)等等,实际上,该参数包含众多的属性,具体请查看控件说明文档中的详细描述。

DotNetFlexGrid1DataHandler方法需要返回一个类型为dotNetFlexGrid.DataHandlerResult的对象,该对象必须提供属性page(当前返回的页号)、属性total(总共的数据条数)、属性table(包含数据的DataTable)。

在这里,我们模拟为Grid提供数据,我们使用控件内置的DemoMemoryTable()产生一个虚拟的DataTable,实际应用中,您需要根据您的需求构建储存数据的DataTable。

我们再次浏览页面,您会发现表格中填充了一些模拟的数据,同时分页器、排序功能、刷新功能均能正常使用了。

其实,我们会发现排序功能似乎无效,表格刷新后但并没有按照我们预期的进行排序,实际上,与其他控件不同,dotNetFlexGrid建议使用服 务端排序,大多数需求中,我们期望的排序功能是针对整个数据库查询的结果集进行排序,而大多数控件或JS 插件提供的仅仅是单页的客户端排序;既然这样,我们为这个例子增加排序处理,请修改你的DotNetFlexGrid1DataHandler方法。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public dotNetFlexGrid.DataHandlerResult DotNetFlexGrid1DataHandler(dotNetFlexGrid.DataHandlerParams p)

{

dotNetFlexGrid.DataHandlerResult result = new dotNetFlexGrid.DataHandlerResult();

result.page = p.page;//设定当前返回的页号

result.total = 100;//总计的数据条数,此处用100进行模拟

result.table = dotNetFlexGrid.DemoMemoryTable(p.page * 100, p.rp);//调用演示的数据生成函数产生模拟数据

//如果传递的参数包含排序设置的话,通过DataView.Sort功能模拟进行当页排序

if (p.sortname.Length > 0 && p.sortorder.Length > 0)

{

System.Data.DataView dv = result.table.DefaultView;

dv.Sort = (p.sortname + ” “ + p.sortorder);

result.table = dv.ToTable();

}

return result;

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

好了,现在可以排序了,同时请原谅我又偷懒了,我们采用DataView.Sort功能模拟进行当前的数据集排序,实际上还是单页排序,但实际上, 此处的数据处理逻辑是应该连接数据库执行实际的查询,排序是否应该交给数据库?的确,分页和排序是很普遍的问题,我们在dotNetFlexGrid的说 明文档中同时提供了一个通用的分页、排序、查询的存储过程配套dotNetFlexGrid使用和参考,请大家自行下载。

最后,似乎还不够,一般我们的表格都会根据用户的条件更改查询结果,我们实现一个异步的查询效果。

我们在页面上增加一个id为”txtName”的文本框和id为”btnSubmit”的按钮以及一小段JavaScript,像下面这个样子。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

<script language=”JavaScript”>

function doSearch() {

var txt = document.getElementById(“txtName”).value;

if (txt) {

var extP = [{ name: “String1”, value: txt}];

dotNetFlexGrid1.applyQueryReload(extP);

}

}

</script>

<div>

<input id=”txtName” type=”text” /> <input id=”btnSubmit” type=”button” value=”查询” onclick=”doSearch();”/>

</div> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

更改下DotNetFlexGrid1DataHandler方法,让其支持查询。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public dotNetFlexGrid.DataHandlerResult DotNetFlexGrid1DataHandler(dotNetFlexGrid.DataHandlerParams p)

{

dotNetFlexGrid.DataHandlerResult result = new dotNetFlexGrid.DataHandlerResult();

result.page = p.page;//设定当前返回的页号

result.total = 100;//总计的数据条数,此处用100进行模拟

result.table = dotNetFlexGrid.DemoMemoryTable(p.page * 100, p.rp);//调用演示的数据生成函数产生模拟数据

//如果传递的参数包含排序设置的话,通过DataView.Sort功能模拟进行当页排序

if (p.sortname.Length > 0 && p.sortorder.Length > 0)

{

System.Data.DataView dv = result.table.DefaultView;

dv.Sort = (p.sortname + ” “ + p.sortorder);

result.table = dv.ToTable();

}

//如果传递的参数包含附加参数的话,再来模拟查询,原谅我真的很懒。

if (p.extParam.ContainsKey(“String1”))

{

System.Data.DataView dv = result.table.DefaultView;

dv.RowFilter = “String1 Like ‘%” + p.extParam[“String1”]+“%'”;

result.table = dv.ToTable();

}

return result;

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

我们通过p.extParam获取到Javascript送出的查询数据(注意之前的js代码中的赋值和刷新表格),然后进行查询并返回结果集;其实,我们通过这种方法,可以很简单的实现与其他各类控件的联动,甚至无数个dotNetFlexGrid

Over,第一个例子到这里了,总结下:

  • 我们需要直接将控件拖拽入页面。
  • 在页面加载时调用InitConfig方法初始化Grid,我们在这里设置表格的宽、高、分页器等参数,同时设置表格需要展示的字段。
  • 为Grid绑定一个类型为dotNetFlexGrid.DataHandlerDelegate数据提供方法,我们在这个方法里响应Grid的动作并返回合适的结果。
  • 我们还可以通过简单的js调用异步控制我们的表格,例子中演示了异步查询和刷新。

不知不觉,似乎写了很多,其实dotNetFlexGrid是非常易用的,3个简单的步骤即可完成一个完全异步的Grid,足以替换掉Asp.net自带的GridView了。

下一次,我们将演示快速查询的功能以及2个表格的联动功能,敬请期待。

BTW:本文的例子包含在整个演示项目中,不幸的是,演示项目的下载需要稍后提供,当然,看到此文的都是多年的ASP.NET老手,如此简单的例子,相信不会给大家带来过多的困惑。

[转载]网上常用免费WebServices集合

mikel阅读(811)

[转载]网上常用免费WebServices集合 – Capricornus – 博客园.

天气预报Web服务,数据来源于中国气象局 公用事业
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

中国股票行情分时走势预览缩略图
http://www.webxml.com.cn/webservices/ChinaStockSmallImageWS.asmx

中国股票行情数据 WEB 服务(支持深圳和上海股市的基金、债券和股票)
http://www.webxml.com.cn/WebServices/ChinaStockWebService.asmx

国内飞机航班时刻表 WEB 服务 公用事业
http://www.webxml.com.cn/webservices/DomesticAirline.asmx

中国电视节目预告(电视节目表) WEB 服务 公用事业
http://www.webxml.com.cn/webservices/ChinaTVprogramWebService.asmx

火车时刻表 (第六次提速最新列车时刻表) 公用事业
http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx

中文 <-> 英文双向翻译 WEB 服务 获得标准数据
http://www.webxml.com.cn/WebServices/TranslatorWebService.asmx

验证码图片 WEB 服务 支持中文、字母、数字 图像和多媒体
http://www.webxml.com.cn/WebServices/ValidateCodeWebService.asmx

中国邮政编码 <-> 地址信息双向查询/搜索 WEB 服务 获得标准数据
http://www.webxml.com.cn/WebServices/ChinaZipSearchWebService.asmx

IP地址来源搜索 WEB 服务(是目前最完整的IP地址数据) 获得标准数据
http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx

国内手机号码归属地查询

http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx

外汇-人民币即时报价

http://webservice.webxml.com.cn/WebServices/ForexRmbRateWebService.asmx

腾讯QQ在线状态 WEB 服务

http://webservice.webxml.com.cn/webservices/qqOnlineWebService.asmx

中文简体字<->繁体字转换 WEB 服务
http://webservice.webxml.com.cn/WebServices/TraditionalSimplifiedWebService.asmx

IP地址搜索 WEB 服务包含中国和国外已知的IP地址数据,是目前最完整的IP地址数据,记录数量现已超过37万条并还在不断更新和增加中
http://webservice.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx

[转载]memCached客户端CPU过高问题的排查

mikel阅读(1492)

[转载]memCached客户端CPU过高问题的排查 – hellofox2000 – 博客园.

公司网站使用了memCached来做分布式缓存,最近有人反映memCached客户端占用CPU过高,怀疑是第三方客户端性能不佳,进而怀疑是文本协议的问题,要求部门自己开发memCached的客户端,使其支持二进制协议。因为重新开发客户端工作量比较大,同时在日常开发中,没有听说过memCached客户端遇到瓶颈。因此对此问题进行了排查。结果发现主要是由于客户端反序列化,类设计不合理造成的。把排查过程分享下,希望对其他人有所帮助。

首先想到是:memCached服务器端内存占满,在清理内存中,造成客户端socket连接不上,不断发生异常。随上服务器查看了memCached的内存占用率,连接数等,发现利用率均很低。暂时先排除服务器端问题。

其次想到可能是第三方在使用socket连接池时,造成资源没有关闭,或者死锁。随对第三方客户端代码粗略读了一遍,并搜索相关文档。未发现异常代码。暂时先排除第三方客户端问题。

最后想到会不会是开发人员在代码编写中出现了问题。随对反映问题的两个产品进行了排查。发现了以下代码。

代码片段1

代码

static Serializer ser = new Serializer(typeof(List<UserModule>)); //using JsonExSerializer;
public static List<UserModule> GetAllUserModule(int userId)
{
string cache = CacheManager.Current.Get<string>(GetCacheKey(userId));
if (!string.IsNullOrEmpty(cache))
{
return ser.Deserialize(cache) as List<UserModule>;
}
else
{
return null;
}
}

public static List<UserModule> SetAllUserModule(int userId, List<UserModule> modules)
{
if (modules != null)
{
string cache = ser.Serialize(modules);
CacheManager.Current.Add(GetCacheKey(userId), cache);
}
else
{
CacheManager.Current.Remove(GetCacheKey(userId));
}
return modules;
}

代码片段2

代码

/// <summary>
/// 聊天室房间
/// </summary>
[Serializable]
public class Room
{
//房间有观看人员数据
List<Viewer> _viewers = null;
List
<string> _blackips = null;
List
<Viewer> _blackviewers = null;
List
<Notice> _notice = null;
List
<Speaker > _speakers = null;
List
<Content> _content = null;

/// <summary>
/// 添加新聊天者
/// </summary>
/// <returns>返回新添加的聊天人员</returns>
public Viewer AddViewer()
{
Viewer vi
= new Viewer();
//MaxViewerID += 1;

//int id = MaxViewerID;
int id = GetViewerID();
vi.Name
= GetViewerName(游客 + id);
//vi.IP = System.Web.HttpContext.Current.Request.UserHostAddress;
vi.IP = 127.0.0.1;
vi.ViewID
= id;
Viewers.Add(vi);
return vi;
}

/// <summary>
/// 添加聊天内容
/// </summary>
/// <param name=”content”>聊天的内容</param>
/// <param name=”viewid”>发言人的id</param>
/// <returns>返回新添加的对象</returns>
public Content AddContent(string content, int viewid)
{
MaxContentID
+= 1;
Content con
= new Content(DateTime.Now, content, viewid, MaxContentID);
Contents.Add(con);
return con;
}
……
}

调用代码为:
Room room = LiveSys.Get(key);
lock (room)
{
if (room.MaxContentID == 0)
{
//ChatContentOp cpo = new ChatContentOp();
//room.MaxContentID = cpo.GetMaxContentID();

room.MaxContentID
= 300;
}
int viewerID = 123124123;
room.AddContent(chatContent, viewerID);
//判断内容是否大于100条。如果大于100条,删除最近的100条以外的数据。
System.IO.File.AppendAllText(@”d:\haha.txt, 最大数值: + room.LimitContentCount + ###############聊天记录数: + room.Contents.Count + \r\n);
if (room.Contents.Count > room.LimitContentCount)
{
room.Contents.RemoveRange(
0, room.Contents.Count room.LimitContentCount);
}
}
LiveSys.Set(key, room);

代码1存在的问题是:

Cache存储的参数类型为object,没有必要先进行一次序列化,然后再进行存储。而序列化是很消耗CPU的。

代码2问题:

代码2实现的是一个在线聊天室,聊天室本身含有访客,发言等内容。在发言时,对聊天室内容进行判断,只显示最近30条。新进来访客直接加到访客别表中。表面上是没什么问题的。但是细想之下有两个问题:

1 聊天室类设计的比较复杂,每次从memCached服务端取得数据后,都要进行类型转换。

2 没有访客清理机制。随着访客的不断进入,对象的体积会不断增大。

对存疑部分编写了代码进行测试。测试结果果然如推测所想。测试结果如下:

场景 写入 读取 大小

(单位)

CPU
次数 时间 平均 次数 时间 平均
本地缓存 10000 0.03125 0 10000 0 0 1k 0
MemClient 10000 19.2656 0.001926 10000 22.75 0.002275 1k
Json1k 1000 2.8437 0.002843 1000 5.375 0.005375 1k
Json8k 1000 3.8593 0.003859 1000 29.0312 0.029031 8k
直播1000人次 1000 38.9375 0.038937 1000 50k
直播8000人次 100 18.25 0.1825 100 350k
500k 100 7.375 0.07375 100 7.09375 0.070937 500k
场景 写入 读取 大小

(单位)

CPU
次数 时间 平均 次数 时间 平均
本地缓存 10000 0.03125 3.125E-06 10000 0.015625 1.5625E-06 1k 0
MemClient 10000 19.78125 0.001978 10000 21.953125 0.002195 1k
Json1k 1000 2.03125 0.002031 1000 6.078125 0.006078 1k
Json8k 1000 2.765625 0.002765 1000 55.375 0.055375 8k
直播1000人次 1000 38.53125 0.038531 1000 50k
直播8000人次 100 17.96875 0.179687 1000 350k
500k 100 7.5 0.075 100 6.5625 0.065625 500k
场景 写入 读取 大小

(单位)

CPU
次数 时间 平均 次数 时间 平均
本地缓存 10000 0.015625 1.5625E-06 10000 0.015625 1.5625E-06 1k 0
MemClient 10000 18.015625 0.001801 10000 25.96875 0.002596 1k 6%
Json1k 1000 1.15625 0.001156 1000 3.078125 0.003078 1k 40%
Json8k 1000 1.859375 0.001859 1000 32.484375 0.032484 8k 50%
直播1000人次 1000 45.046875 0.045046 1000 50k 30-40%
直播8000人次 100 31.703125 0.317031 100 350k 50%
500k 100 7.0625 0.070625 100 6.421875 0.064218 500k 6%

直播1000人次(当天一共有1000人访问,数据来源于运营检测),留言内容为30条时,Room体积大概为:57K


直播1000人次(当天一共有8000人访问,数据来源于运营检测),留言内容为30条时,Room体积大概为:350k

根据图表可以看到以下情况:处理时间、CPU利用率和数据量大小,序列化,类复杂性都有关系。

序列化问题(类型转换)对性能影响最为明显(可在场景”json1k”、场景直播中看到)。在Json1k中,存储对象和前几个场景是相同的,处理时间也相差不大,较大区别是CPU利用率由5%左右增长到40%左右(反序列化时尤为明显)。在场景直播系统中,不存在序列化问题,但是其对象属性中存在访客繁衍等多个复杂对象,造成其在处理时需要处理过多的类型转换,同时其体积不断增大。

存储对象的大小和处理时间存在一定关系,例如场景”500k”,其处理时间增长,但是其CPU利用率并未提高,其时间增长是由于对象传输造成。

本地缓存在内存中进行寻址和类型转换,涉及不到Socket连接,网络传输,序列化操作,所以其处理相当快。

就测试结果看:

本地缓存性能大约是分布式缓存性能的100倍左右。而出问题的聊天室除了CPU增高以外,其性能更比分布式缓存再降低40倍(直播1000人次)到200倍(直播8000人次)。综合来看,聊天室的分布式缓存比本地缓存降了4000倍,甚至更多。

但是,还没有完。

对于第二个问题,更改类设计,清楚无效访客,即可解决。

但是第一个问题,为什么用户在存储之前,先进行json序列化呢?嗯,这是一个问题。

遂问之。

答曰,有些类直接使用第三方客户端存储时,直接存储报错,所以先序列化为json类型,取值时再反序列化回来。

嗯,还有这事?

开发人员说了相关代码。

代码

interface IUser
{
String UserId{
get; set;}
String UserName{
get; set;}
}

[Serializable]
class UserInfo : IUser
{
String UserId{
get; set;}
String UserName{
get; set;}
}
[Serializable]
class Game
{
IUser User{
get; set;}
String UserName{
get; set;}
}

他说:Game对象在直接使用memCachedClient时,是不能被二进制序列化的,因为其User属性类型为IUser,为一个接口。因此想了一个解决方法,即先将Game对象进行 json序列化将其变为字符串,然后将字符串存储到memCached

原来是这样。

接着又查看了memCachedClient源代码,其需要将对象进行二进制序列化,然后进行存储。接口属性不能被序列化,遂又对序列化问题进行了测试(见附件)。测试结果显示上述代码直接进行二进制序列化是可以的,同时直接使用第三方客户端也是可以可行的。

问题出在哪?难道是没有加[Serializable]

一查果然:一个Serializable引发的血案。。。

记得有人说过,慎用分布式,能不用尽量不用。

一方面在性能上确实下降很多,分布式存储主要性能消耗在以下几个方面:协议解析,Socket连接,数据传输,序列化/类型转换。

一方面在使用场景和类设计上要求也更加严格。个人认为memCached是不太适合存储特别大的文件的。虽然有人说网上已经有用来存储视频的。

还有几个问题希望知道的朋友回答下:

1 有没有.Net方面的memCached客户端支持二进制协议和一致性的?

2 测试中发现,当memCached设置缓存过小时(例如64M),当其内存使用已经到62M时,再进行存储,新存储的内容再取出来就是空值,不知道是什么原因。

文章中用到的源码:下载源码

[转载]使用IIS内置压缩功能,增加网站访问速度

mikel阅读(1034)

[转载]使用IIS内置压缩功能,增加网站访问速度 – Capricornus – 博客园.

HTTP 压缩是在Web服务器和浏览器间传输压缩文本内容的方法。HTTP压缩采用通用的压缩算法如gzip等压缩HTML、JavaScript或CSS文件。压缩的最大好处就是降低了网络传输的数据量,从而提高客户端浏览器的访问速度。当然,同时也会增加一点点服务器的负担。Gzip是比较常见的一种HTTP 压缩算法。

默认的IIS中是有GZIP.dll组件的,我们只要开启即可.操作步骤如下:

1.开启HTTP压缩功能

在IIS中右键网站属性->服务选项卡->选中<压缩应用程序文件><压缩静态文件>两个选项.如图

2.在Web服务扩展中增加一个新扩展

右键Web服务扩展->增加一个新的Web服务扩展->要求的文件C:\WINDOWS\system32\inetsrv\gzip.dll ->设置扩展状态为允许.如图

3.修改IIS配置文件 (注意: 一定要先备份MetaBase.xml文件)

1).打开C:\Windows\System32\inetsrv\MetaBase.xml文件.

2).使用ctrl+f查找 Location =”/LM/W3SVC/Filters/Compression/gzip”与      Location =”/LM/W3SVC/Filters/Compression/deflate”

3).将两个节点的配置修改为如下配置

代码

<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/deflate" HcCompressionDll="%windir%\system32\inetsrv\gzip.dll" HcCreateFlags="0" HcDoDynamicCompression="TRUE" HcDoOnDemandCompression="TRUE" HcDoStaticCompression="true" HcDynamicCompressionLevel="9" HcFileExtensions="htm html txt js css swf xml" HcOnDemandCompLevel="9" HcPriority="1" HcScriptFileExtensions="asp aspx dll exe" > </IIsCompressionScheme> <IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/gzip" HcCompressionDll="%windir%\system32\inetsrv\gzip.dll" HcCreateFlags="1" HcDoDynamicCompression="TRUE" HcDoOnDemandCompression="TRUE" HcDoStaticCompression="true" HcDynamicCompressionLevel="9" HcFileExtensions="htm html txt js css swf xml" HcOnDemandCompLevel="9" HcPriority="1" HcScriptFileExtensions="asp aspx dll exe" > </IIsCompressionScheme>

其中HcFileExtensions中是需要静态压缩的后缀,你也可以添加doc,xsl等文件内容

HcScriptFileExtensions 则是动态压缩的后缀

4.修改完毕后,保存文件,重启IIS即可.(如果无法保存,代表IIS正在使用中,可以先关闭IIS服务)

另外GZIP检测地址为:http://tool.chinaz.com/Gzips/

可以看出博客园也是进行过GZIP加速的:

[转载]ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》

mikel阅读(877)

[转载]ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》 – JasenKin – 博客园.

在15分钟内用ASP.NET MVC创建一个电影数据库应用程序

Stephen Walther 从头开始到结束建立了整个数据驱动ASP.NET MVC应用程序。这个教程对于那些刚刚接触ASP.NET MVC框架以及想要获得一种建立ASP.NET MVC应用程序的过程的新人是一个很好的介绍。
这个教程的目的就是给你一种“它会是什么样子”去创建ASP.NET MVC应用程序的理念。在这一课中,从开始到结束,我将直接建立一个完整ASP.NET MVC应用程序。我向你展示如何建立一个简单的数据驱动应用程序,演示如何列出,创建和编辑数据库记录。

为简化创建应用程序的过程,我们会充分利用Visual Studio 2008的功能。我们会让 Visual Studio为我们的控制层,模型层,视图层生成初始代码和内容。

如果你已经使用Active Server Pages 或者 ASP.NET来工作,那么你将对ASP.NET MVC很熟悉。ASP.NET MVC 视图与ASP应用程序的页面非常相似。并且与传统的ASP.NET Web Forms 应用程序一样, ASP.NET MVC 为你提供了丰富的语言和.NET框架类。我希望这篇教程将让你了解到创建ASP.NET MVC应用程序的经验与创建ASP or ASP.NET Web Forms 应用程序的相似点和不同点.

这部电影数据库应用程序的概述

因为我们的目标是让事情简单化,我们将建立一个非常简单的电影数据库应用程序。我们的简单的电影的数据库应用程序将使我们能够做的三件事:

1。列出一系列电影数据库记录
2。创建一个新的电影数据库记录
3。编辑一个现有的电影数据库记录
再次,因为我们想让事情变得简单,我们会利用ASP.NET MVC框架少量的特点来建立我们的应用程序。例如,我们不会利用测试驱动开发。

为了创造我们的应用程序,我们需要完成下列步骤:

1。建立 ASP.NET MVC Web Application 项目
2。创建数据库
3。创建数据库模型层
4。建立ASP.NET MVC控制层
5。建立ASP.NET MVC视图层

篇前部分(准备工作)
你将需要Visual Studio 2008 或者 Visual Web Developer 2008 Express来建立一个 ASP.NET MVC 应用程序。你还需要下载 ASP.NET MVC  MVC框架。

如果你还没有安装Visual Studio 2008,你可以从这个网站下载一个90天试用版的Visual Studio 2008:
http://msdn.microsoft.com/en-us/vs2008/products/cc268305.aspx

或者,你可以使用Visual Web Developer Express 2008创建ASP.NET MVC应用程序。如果你决定要用Visual Web Developer Express ,你就必须已经安装 Service Pack 1 。你可以从这个网站下载Visual Web Developer 2008 Express with Service Pack 1 :

http://www.microsoft.com/downloads/details.aspx?FamilyId=BDB6391C-05CA-4036-9154-6DF4F6DEBD14&displaylang=en

在你安装完Visual Studio 2008 或者 Visual Web Developer 2008以后,你需要安装ASP.NET MVC 框架。你可以从以下网站下载ASP.NET MVC 框架:

http://www.asp.net/mvc/

创建一个ASP.NET MVC Web Application 项目
让我们使用 Visual Studio 2010创建ASP.NET MVC Web Application项目来开始。选择菜单选择文件,新建,项目,你将会看到这个新项目的对话框。选择C#作为编程语言以及选择ASP.NET MVC 2 Web 应用程序项目模板。给你的项目命名为MovieApp和点击“确定”按钮。

图1

当你创建一个新的MVC Web Application项目时 Visual Studio提示你去创造一个独立的单元测试项目,如图2所示。因为在这一课中我们不会创建测试,选择“否”选项,并点击“确定”按钮。

图2

ASP.NET MVC应用程序有一系列标准的文件夹:模型、视图和控制的文件夹。你可以在“解决方案资源管理器”中看到这一系列标准的文件夹。我们需要添加文件到模型层,视图层和控制层文件夹,用以创建我们的电影的数据库应用程序。

当你使用Visual Studio创建一个新的MVC应用程序,你得到了一个示例应用程序。因为我们要从头开始,我们需要删除该示例应用程序的内容。你需要删除以下的文件和文件夹。
•Controllers\HomeController.cs
•Views\Home
创建数据库
我们需要创建一个数据库来保存我们的电影数据库记录。幸运的是,Visual Studio包含一个免费的SQL Server Express。遵循这些步骤来创建数据库。

1。在“解决方案终于管理器”中,右键点击该App_Data文件夹,选择菜单的选项“添加”,“新建”。
2。选择数据分类和选择SQL Server数据库模板(见图3)。
3。命名新数据库MoviesDB.mdf,然后点击“增加”按钮。
在你创造你的数据库后,你可以双击位于App_Data文件夹中的MoviesDB.mdf文件来连接这个数据库。双击MoviesDB.mdf文件,打开服务器资源管理器的窗口。
图3

接下来,我们要创造一个新数据库表。从服务器资源管理器窗口,右键点击该表格的文件夹“表”,并选择菜单选项“添加新表”。选择这个菜单选项打开数据库

表设计器。创建以下数据库的栏目。

第一列,Id列,有两个特殊的属性。首先,你需要标记Id列为主键列。选择 后,点击Id列的“设置主键”选项(它是图标看起来像一个钥匙)。其次,你需要标记Id列作为一个标记列。在这个“列属性”窗口,向下转动滚轮至“标识规 范”并且展开该节点,改变“(是标识)”为“是”。当你完成,表应该看起来像图4。

图4

最后一步是保存这个新表。点击“保存按钮,并且给新表命名为Movies。

当你完成创建表,加上一些电影记录到这个表格中。在服务器资源管理器中,右键点击Movies表,选择菜单选项显示表的数据。输入你最喜欢的电影清单(见图5)。

创建模型层
我们下一步要创建一系列的类来代表我们的数据库。我们需要创建一个数据库模型。我们将充分利用微软实体框架来自动生成我们的数据库模型。

ASP.NET MVC 框架与微软实体框架是无关联的。你可以通过很多的对象-关系映射(OR/ M)工具来创建你的数据库模型类,其中包括LINQ to SQL, Subsonic、NHibernate。

遵循这些步骤来展开实体数据模型向导。

1。在解决方案资源管理器窗口中,右键点击该模型层的文件夹,选择“添加”,“新建项”。
2。选择“数据”分类和选择ADO.NET 实体数据模型模板。
3。将你的数据模型命名为MoviesDBModel.edmx,然后点击“添加”按钮。

图7

你点击“添加”按钮后,这个实体数据模型向导出现(见图)。遵循这些步骤来完成向导。

1。在选择模型内容这一步,选择“从数据库生成”的选择。
2。在选择你的数据连接这一步,使用这个MoviesDB.mdf数据连接以及MoviesDBEntities作为连接设置。单击下一步按钮。

图8
3。在选择你的数据库对象一步,扩大表节点,选择Movies表。输入的命名空间MovieApp,单击“完成”按钮。

图9

在你完成实体数据模型向导,实体数据模型设计器将开启。设计器应该显示 Movies数据库表(见图10)。

在我们继续之前,我们需要做一点改变。这个实体数据向导生成一个Movies的模型类,代表 Movies数据库表。因为我们将使用这个 Movies 类代表某一特定的电影,我们需要修改这个类的名称为Movie而不是Movies(单数而不是复数)。

在设计器的表面,双击这个类的名称以及更改这个类名为Movie。在标识这个更改以后,点击保存按钮来生成Movie类。

创建ASP.NET MVC 控制层
下一步是要创建这个ASP.NET MVC 控制层。一个控制层负责控制用户和 ASP.NET MVC 应用程序的相互作用。

遵循这些步骤:

1。在解决方案资源管理器中,右键点击该 Controllers文件夹,并选择菜单选项“添加控制器”。
2。在对话框中输入框中,键入HomeController和勾选“为Create,Update…”
(见图11)。

3。点击“添加”按钮来添加新的控制器。
在您完成这些步骤,该控制器在Listing 1就创建了。注意到它包含的Index, Details, Create, and Edit这些方法。在接下来的章节,我们将添加所需的代码来使这些方法来工作。
Listing 1 – Controllers\HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MovieApp.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/

public ActionResult Index()
{
return View();
}

//
// GET: /Home/Details/5

public ActionResult Details(int id)
{
return View();
}

//
// GET: /Home/Create

public ActionResult Create()
{
return View();
}

//
// POST: /Home/Create

[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here

return RedirectToAction(“Index”);
}
catch
{
return View();
}
}

//
// GET: /Home/Edit/5

public ActionResult Edit(int id)
{
return View();
}

//
// POST: /Home/Edit/5

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here

return RedirectToAction(“Index”);
}
catch
{
return View();
}
}

//
// GET: /Home/Delete/5

public ActionResult Delete(int id)
{
return View();
}

//
// POST: /Home/Delete/5

[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here

return RedirectToAction(“Index”);
}
catch
{
return View();
}
}
}
}
列出数据库记录
这个Home controller中的Index()方法是ASP.NET MVC 应用程序的默认的方法。当你运行ASP.NET MVC 应用程序,该Index()方法是第一个被调用的控制器的方法

我们将使用 Index()方法来显示Movies数据库表的一些数据。我们将使用Index()方法,利用数据库模型类来检索Movies数据库记录。

在Listing 2,我已经修改了HomeController类 ,以便它包含了1个新的_db所有字段。MoviesDBEntities类代表我们的数据库模型,我们将使用这类与数据库通信。

在Listing 2,我还修改了Index()方法。这个Index()方法使用MoviesDBEntities类来检索Movies 数据库表的所有记录。表达式_db.MovieSet.ToList()返回Movies数据库表所有的记录列表。

这个movies的列表传递给view层。

Listing 2 – Controllers/HomeController.cs (修改的Index()方法)。

public class HomeController : Controller
{

//
// GET: /Home/

private MovieApp.Models.MoviesDBEntities _db = new

Models.MoviesDBEntities();
public ActionResult Index()
{
//return View();
return View(_db.Movies.ToList());
}
….
}
Index()方法将返回一个命名为Index的视图view。我们需要创建这个view来显示movies数据库记录的列表。遵循这些步骤:

在打开之前的对话或不加观课程将出现在视图数据等级的下拉列表。你应该生成你的项目(选择菜单选项“生成”,“生成解决方案”)
1。在代码编辑窗口中右键点击该Index()方法和选择菜单选项“添加视图”(见图13)。
2。在对话框的角度,勾选“创建强类型视图”复选框。
3。从“视图数据类”下拉列表中,选择值MovieApp.Models.Movie。
4。从“视图内容”下拉列表中,选择值List。
5。点击“添加”按钮来创造新的view(见图3)。
在您完成这些步骤,一个新命名Index.aspx的View被添加到Views\Home 目录。这个Index view的内容都包含在Listing 3.。

Listing 3 – Views\Home\Index.aspx

<%@ Page Title=”” Language=”C#

MasterPageFile=”~/Views/Shared/Site.Master”

Inherits=”System.Web.Mvc.ViewPage<IEnumerable<MovieApp.Models.Movie>>”

%>

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent”

runat=”server”>
Index
</asp:Content>

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent”

runat=”server”>

<h2>Index</h2>

<table>
<tr>
<th></th>
<th>
Id
</th>
<th>
Title
</th>
<th>
Director
</th>
<th>
DateReleased
</th>
</tr>

<% foreach (var item in Model) { %>

<tr>
<td>
<%: Html.ActionLink(“Edit”, “Edit”, new { id=item.Id })

%> |
<%: Html.ActionLink(“Details”, “Details”, new {

id=item.Id })%> |
<%: Html.ActionLink(“Delete”, “Delete”, new {

id=item.Id })%>
</td>
<td>
<%: item.Id %>
</td>
<td>
<%: item.Title %>
</td>
<td>
<%: item.Director %>
</td>
<td>
<%: String.Format(“{0:g}”, item.DateReleased) %>
</td>
</tr>

<% } %>

</table>

<p>
<%: Html.ActionLink(“Create New”, “Create”) %>
</p>

</asp:Content>

这个Index view 将movie数据库表所有记录显示在HTML表格。这个视图包含一个foreach循环,它遍历ViewData.Model属性所表示的每一个 movie。如果你通过按F5键运行应用程序,你将会看到网页如图  所示。

图14

创建新的数据库记录

我们在前一部分创建 的Index view 包括一个为创建新数据库记录的链接。

Homecontroller包含两种 Create()方法。第一个的 Create()方法没有参数。这个重载的 Create()方法被用来显示HTML表单。

第二个Create()方法有一个FormCollection参数。当这个创建一个新的movie的HTML表单回传到服务器时,这个重载的 Create()方法将被调用。注意这第二个Create()方法有一个AcceptVerbs属性,它将阻止这个方法被调用,除非HTTP POST操作执行了。

这个第二个Create()方法已经在Listing 4更新过的HomeController类中被修改了。新版本的Create()方法接受一个Movie 参数和包含插入一个新的movie到movies数据库表的逻辑。

注意绑定属性。因为我们不想从HTML表单更新影片Id属性,我们需要明确排除该属性。
Listing 4 – Controllers\HomeController.cs (modified Create method)
//
// POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Create([Bind(Exclude = “Id”)] Movie movieToCreate)
{

if (!ModelState.IsValid)

return View();

_db.AddToMovies(movieToCreate);
_db.SaveChanges();
return RedirectToAction(“Index”);

}

Visual Studio ,使它容易创建表格来创建一个新的movie数据库记录(见图)。遵循这些步骤:

1。在代码编辑窗口,右键单击Create()方法,选择菜单选项“添加视图”。
2。确认勾选“创建强类型视图”。
3。从“视图数据类”下拉列表中,选择值MovieApp.Models.Movie。
4。从“视图内容”下拉列表中,选择值 Create。
5。点击“添加”按钮来创造新的view(见图3)。


Visual Studio 自动生成视图,如 Listing 5所示。这一view 包含HTML表单,它包含与Movie类的每个属性相对应的字段。

Listing 5 – Views\Home\Create.aspx

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage<MovieApp.Models.Movie>” %>

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>
Create
</asp:Content>

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

<h2>Create</h2>

<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>

<fieldset>
<legend>Fields</legend>

<div class=”editor-label”>
<%: Html.LabelFor(model => model.Id) %>
</div>
<div class=”editor-field”>
<%: Html.TextBoxFor(model => model.Id) %>
<%: Html.ValidationMessageFor(model => model.Id) %>
</div>

<div class=”editor-label”>
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class=”editor-field”>
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>

<div class=”editor-label”>
<%: Html.LabelFor(model => model.Director) %>
</div>
<div class=”editor-field”>
<%: Html.TextBoxFor(model => model.Director) %>
<%: Html.ValidationMessageFor(model => model.Director) %>
</div>

<div class=”editor-label”>
<%: Html.LabelFor(model => model.DateReleased) %>
</div>
<div class=”editor-field”>
<%: Html.TextBoxFor(model => model.DateReleased) %>
<%: Html.ValidationMessageFor(model => model.DateReleased) %>
</div>

<p>
<input type=”submit” value=”Create” />
</p>
</fieldset>

<% } %>

<div>
<%: Html.ActionLink(“Back to List”, “Index”) %>
</div>

</asp:Content>

在你创建 Create 视图后,你可以添加新的Movie 记录到数据库。按下F5键运行你的应用程序和点击Create New 的链接,你将看到如图13所示的表格。如果你完成并提交表单、一个新movie数据库记录诞生了。

注意,你自动获得表单验证。如果你忽略输入movie的发行日期,或者你输入一个无效的发布日期,那么这个表单被重新显示,并且发布日期字段将高亮显示。
编辑现有的数据库记录

在之前的部分,我们讨论了如何列举和创造新的数据库记录。在这最后一节中,我们将讨论如何修改现有的数据库记录。

首先,我们需要生成编辑表单。 因为Visual Studio将为我们自动生成编辑表单,所以这一步很容易。在Visual Studio代码编辑器中,打开HomeController.cs类 ,遵循以下步骤:

1。在代码编辑窗口,右键单击 Edit()方法,选择菜单选项“添加视图”。
2。确认勾选“创建强类型视图”。
3。从“视图数据类”下拉列表中,选择值MovieApp.Models.Movie。
4。从“视图内容”下拉列表中,选择值  Edit。
5。点击“添加”按钮来创造新的view(见图3)。

完成这些步骤,将添加一个Edit.aspx的视图到Views\Home文件夹中。这一视图包含用来编辑一个movie记录的HTML表单。Edit view包含一个相应于movie Id属性的HTML表单字段。因为你不想让人们编辑这个Id属性的值,你应该移除这个表单字段。

最后,我们还需要修改Home controller,使它支持编辑数据库记录。最新的HomeController类如Listing 6所示。

Listing 6 – Controllers\HomeController.cs (Edit methods)

//
// GET: /Home/Edit/5

public ActionResult Edit(int id)
{
//return View();
var movieToEdit = (from m in _db.Movies

where m.Id == id

select m).First();

return View(movieToEdit);
}
[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Edit(Movie movieToEdit)
{

var originalMovie = (from m in _db.Movies

where m.Id == movieToEdit.Id

select m).First();

if (!ModelState.IsValid)

return View(originalMovie);

_db.ApplyCurrentValues<Movie>(originalMovie.EntityKey.EntitySetName, movieToEdit);
//_db.ApplyPropertyChanges(originalMovie.EntityKey.EntitySetName, movieToEdit);

_db.SaveChanges();

return RedirectToAction(“Index”);

}

在 Listing 6,我已经为2个重载的Edit()方法增添了更多的逻辑。第一个Edit()方法将返回相对应的Id传递参数的方法的movie数据库记录。第二个重载方法执行数据库中记录的更新。

注意,你必须检索到原来的movie,然后调用ApplyCurrentValues<Movie>、更新现有的在数据库中的movie。

总结
这个教程的目的就是让你初步了解如何创建一个ASP.NET MVC应用程序。我希望你们发现,创建一个 ASP.NET MVC web 应用程序与创建ASP 或者 ASP.NET应用程序是非常相似的。

在这一课中,我们只是解释ASP.NET MVC 框架的最基本的特征。在后续的教程中,我们将深入更多的主题,如controllers, controller actions, views, view data和HTML helpers。

[转载]11个非常棒的CSS3实现的图片画廊

mikel阅读(912)

[转载]11个非常棒的CSS3实现的图片画廊 – 梦想天空 – 博客园.

CSS3给WEB开发带来了革命性的影响,以前很多需要JavaScript实现的复杂效果,现在使用简单的CSS3就能实现。下面这些绚丽的图片画廊效 果就是用CSS3实现的。还有件非常有趣的事就是很多人都在使用宝丽来效果。(提示:点击图片即可浏览Demo,为了能查看完整效果,请使用 Safari、Chrome、Opera浏览器浏览)

Polaroid from Tutorialzine

来自Tutorialzine得宝丽来效果,CSS3实现的旋转,图片可拖动,还有Drop To Share功能。

(更多…)

[转载]ASP.NET实现RSS订阅(Rss Toolkit 1.0)

mikel阅读(1082)

[转载]ASP.NET实现RSS订阅(Rss Toolkit 1.0) – tryandtry.cn – 博客园.

RSS具有实现成本低、推广速度快的优点,已成为很多报纸媒介电子网站中的一项重要推广技术。本节将介绍如何在网站中实现RSS功能,此功能主要包括两部分:订阅功能和提供阅读器工具功能。今天讲讲订阅功能的实现技术。
1 使用Microsoft提供的RSS工具包
为了让用户可以在ASP.NET 2.0中方便地使用RSS技术,Microsoft提供了一个RSS工具包,使用户可以简单地实现RSS的订阅和阅读功能。
这个工具包提供了“RssDataSource”和“RssHyperLink”两个控件,开发人员通过对两个控件的拖曳,就可以轻松实现站点的RSS功能。
声 明 本工具全名为“RssToolkit-1-0-0-1”,支持C#语言。读者可从Microsoft站点下载到最新版本Rss Toolkit 2.0,但此版本对于由后台实现复杂的RSS阅读效果有点困难,而RssToolkit 1.0又难以找到,如果你们需要的话点击此处留言,我到时发给你们。

下面将介绍如何把工具包添加到VS 2005的工具箱中。
(1)打开VS 2005,新建一个网站“WebRSS”。
(2)打开“Default.aspx”页面,切换到设计视图,此时工具箱为可用状态。
(3)右击工具箱中的“常规”选项卡,在弹出的菜单中,单击“选择项”菜单命令,弹出“选择工具箱项”对话框,如图1所示。

图1 选择“工具箱”对话框

(4)单击“浏览”按钮,打开文件搜索对话框,如图2所示。

图2 文件搜索对话框

(5)在“查找范围”下拉框中,找到工具包所在的文件夹下的“bin”文件夹,并选中文件夹中的“RssToolkit.dll”文件。
(6)单击“打开”按钮,系统回到“选择工具箱项”对话框,此时系统自动选中dll文件中带的两个控件。
(7)单击“确定”按钮,此时在“常规”选项卡中,多了两个控件:“RssDataSource”和“RssHyperLink”。
至此,工具控件已经加载完毕,可以在VS 2005中使用Microsoft提供的RSS工具包了。
1.1 一个简单的RSS阅读器
本节将使用ASP.NET 2.0提供的数据控件,通过RSS工具箱中的“RssDataSource”数据源控件,实现一个只有一列的网格频道列表,并通过导航的方式显示频道的内容。具体步骤如下。
(1)切换到设计视图,将一个数据控件“DataList”控件拖曳到界面中。
(2)再将一个数据源控件“RssDataSource”控件拖曳到界面中。
(3)在“RssDataSource”控件的任务列表中,只有一项“配置数据源”,单击此菜单命令,弹出地址输入对话框,如图3所示。

图3 输入RSS地址对话框

(4)在地址文本框内,输入“http://www.tryandtry.cn/index.xml”,此处提供一个标准的RSS文件,并提供多个文章项。
(5)单击“OK”按钮,返回到设计视图。
(6)编辑数据控件“DataList”的绑定项,具体设置如代码清单1-1所示。注意此处已经通过属性“DataSourceID”,将“DataList”控件的数据源绑定到“RssDataSource”控件上。
代码清单1-1 DataList控件的数据源绑定设置
<asp:DataList ID=”DataList1″ runat=”server” DataSourceID=”RssDataSource1″>
<ItemTemplate>
title:
<asp:Label ID=”titleLabel” runat=”server” Text='<%# Eval(“title”) %>’ />
<br />
link:
<asp:Label ID=”linkLabel” runat=”server” Text='<%# Eval(“link”) %>’ />
<br />
description:
<asp:Label ID=”descriptionLabel” runat=”server”
Text='<%# Eval(“description”) %>’ />
<br />
pubDate:
<asp:Label ID=”pubDateLabel” runat=”server” Text='<%# Eval(“pubDate”) %>’ />
<br />
<br />
</ItemTemplate>
</asp:DataList>
//以下是RSS控件的代码
<cc1:RssDataSource ID=”RssDataSource1″ runat=”server”
Url=”http://www.tryandtry.cn/index.xml“>
</cc1:RssDataSource>
运行效果图:

图4 运行效果图(在此没对代码进行美化,大家学习时就改改)

(7)此时RSS的读取地址和数据控件的绑定内容都已经设置完毕。按“Ctrl+S”键保存页面的设计。
(8)将此页设计为起始页,按F5键运行程序,测试能否正确显示订阅的RSS新闻列表,运行结果如图4所示。
1.2 一个复杂的RSS阅读器
上一小节主要讲解了一个简单的阅读器的制作过程,本节将通过一个复杂的数据控件“GridView”,实现一个频道列表网格,其中列出频道的主题、链接和描述等信息,并采用数据源后绑定的技术为“GridView”控件配置数据源。具体实现步骤如下。
(1)在网站根目录下,添加一个Web窗体“RSSChanel”。
(2)切换到设计视图,将一个“GridView”控件拖曳到界面中,并设计其样式,具体样式如代码清单1-2所示。因为采用数据源后绑定的技术,此处不需为“GridView”控件配置数据源。
代码清单1-2 GridView的样式配置源HTML代码
<asp:GridView ID=”GridView1″ runat=”server” CellPadding=”4″ ForeColor=”#333333″
GridLines=”None”>
<FooterStyle BackColor=”#5D7B9D” Font-Bold=”True” ForeColor=”White” />
<RowStyle BackColor=”#F7F6F3″ ForeColor=”#333333″ />
<PagerStyle BackColor=”#284775″ ForeColor=”White” HorizontalAlign=”Center” />
<SelectedRowStyle BackColor=”#E2DED6″ Font-Bold=”True” ForeColor=”#333333″ />
<HeaderStyle BackColor=”#5D7B9D” Font-Bold=”True” ForeColor=”White” />
<EditRowStyle BackColor=”#999999″ />
<AlternatingRowStyle BackColor=”White” ForeColor=”#284775″ />
</asp:GridView>
(3)按F7键进入“RSSChanel”页面的代码界面。
(4)必须先添加对RSS工具所在的命名空间的引用,语法是:“Using RssToolkit;”。
(5)在“Page_Load”事件中,调用RSS工具的方法,实现:GridView,控件的数据源绑定,具体实现代码如清单1-3所示。
代码清单1-3 GridView的数据源后绑定代码
using RssToolkit;
public partial class RSSChanel : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//创建一个频道
GenericRssChannel c = GenericRssChannel.LoadChannel(“http://www.tryandtry.cn/index.xml“);
//为GridView绑定数据源
//数据源来自频道中的所有项目
GridView1.DataSource = c.SelectItems();
GridView1.DataBind();
}
}
(6)全部完成后,按“Ctrl+S”键保存所做的设计。
(7)将此页设置为起始页,按F5键运行程序,测试网格绑定的频道列表是否正常导航,最终运行界面如图5所示。

图5 复杂阅读器运行界面