2、核心问题还是要能解决“安全”“随时”“随地”和“快速”等问题,并承若数据足够的私有性(哪家Saas敢承若承担由于数据泄露所引起的损失)
3、基于富客户端和瘦客户端允分结合的Saas的补分:
1)、瘦客户端:如阿里巴巴的网站,并不断增加Ajax成份
2)、富客户端:优势,可离线和丰富操作等。一方面是IM工具(淘宝旺旺等),另一方面是WPF/Flex
值得关注! 阅读全文
2007-06-13 15:23 作者: 针式个人知识库管理【评论:2】【阅读:342】
看到csdn上n多人问同样的问题,ajax乱码等等的,想做个总结,不对的地方请各位指教。
我所说的环境是asp.net web应用,其他web开发应用一个道理。
开发国际1.首先你项目所有的东东(主要指各种文件,包括后台代码、资源文件等)采用utf-8文件编码,这一步解决了文件编码问题(确保你的文件真正应用了或转成了utf-8编码,用转换工具或vs的高级存储选项)
2.把你所有的web页面meta中指定charset为utf-8(可以为link、script同时指定charset),这样你从页面发出的请求(声明一点这个请求非ajax请求,ajax请求另作处理),如点击按钮产生的post请求等都是以utf-8传输内容的了
3.做了2的步骤之后,就要求服务器端晓得你的client发来的http请求默认编码的是utf-8的了,一旦它知道了,你在服务端取request中的参数就也不必要做单独的utf-8解码处理了,这个在asp.net中用web.config通知web server 的asp.net处理引擎,在其中system.web下加入如下配置:
4.解决ajax请求的编码问题,就是让ajax求不采用默认的编码传输数据,而是和我们的系统统一采用utf-8编码,这个要根据你使用的具体的js lib进行设置,prototype中默认用utf-8(如果没有的话,你可以用ajax的options选项加入encoding:'utf-8'),用dojo的话默认是ansi,各位可以按需设置。另外对于裸写ajax请求的用户你可以这样指定:
request.setRequestHeader('Content-type','application/x-www-form-urlencoded; charset=utf-8');
5.稍微要注意的另一点是,对于get请求(或凡涉及到url传递参数的),被传递的参数都要先经encodeURIComponent方法处理
就总结这五点,有问题地方再交流,本人有总结疏漏的地方请指正,之前我们项目中的多言语、ajax及普通请求乱码问题完全解决了
2007-06-13 15:23 作者: 针式个人知识库管理【评论:2】【阅读:342】
摘要
本期共有8篇文章:
- ASP.NET AJAX Control Toolkit版本更新
- 技巧和提示:ASP.NET AJAX 1.0和用户控件
- 创建自定义Provider
- 在Windows、Mac和Linux上的多种浏览器中测试你的站点
- 弹跳小球的动画性能测试——比较各种实现方法
- 调试ASP.NET客户端JavaScript脚本
- JavaScript困境
- Microsoft对决TestDriven.NET - 06 June 2007
[1] Updated Toolkit Release Now Available (ASP.NET AJAX Control Toolkit版本更新)
似乎自打ASP.NET AJAX发布了1.0版本之后,这部分的动向就越来越少了。众人都被SilverLight吸引了过去……不过沉浸了几个月之后,ASP.NET AJAX Control Toolkit却突然来了一次版本更新。
这次版本更新并没有什么破坏性的变化,修复了100多个Bug,并添加了一些丰富的功能,例如:
- VS设计器对TabContainer的支持。
- 能够与ASP.NET validatiors完美集成使用。
- 添加了更多的客户端事件。
- 在VS中自动生成一些服务器端方法。
- 脚本组合。
- 动态上下文支持。
对于第5项功能,将大大减少页面的加载时间。先看看以前版本吧:

现在就好多了:

[2] Tips and Tricks: ASP.NET AJAX 1.0 and User Controls (技巧和提示:ASP.NET AJAX 1.0和用户控件)
ASP.NET AJAX 1.0和用户控件一起使用的时候,往往会让开发者产生很多疑问。常见的有ScriptManager的位置,UpdatePanel的设定,加载用户控件的时机等等。这篇文章简要分析了这类常见问题,并给出了一些作者自己的观点,有需要的朋友不妨参考一下。
作者的另一篇文章《Tip and Tricks: ASP.NET 2.0 AJAX 1.0 Extensions and Master Pages》则讨论了ASP.NET AJAX 1.0和Master Page之间的关系,同样值得一看。
[3] Working with Custom Providers(创建自定义Provider)
ASP.NET 2.0中引入的一个非常重要的概念就是Provider模型,这种模型为我们开发者提供了非常强大的自定义扩展功能,让我们几乎可以随时及项目的需求任意定制某个复杂ASP.NET功能的具体实现流程。
不过创建自定义的Provider却似乎并不是件容易的事情,这篇文章就通过一个示例程序详细介绍了创建的过程。其中语言组织非常不错,行文也比较流畅。若你想提高一下自己的ASP.NET功底,那么花点时间看看这篇文章将会是个不错的主意。
与这篇文章相关的还有同一作者写的《Working with Custom Provider Controls》,这篇文章根据上一篇文章中的Provider编写了一些控件,非常有意思。
[4] browsershots.org - Test your site in a variety of browsers on Win, Mac, and Linux (在Windows、Mac和Linux上的多种浏览器中测试你的站点)
browsershots.org提供了一个免费的,在Windows、Mac和Linux上的多种浏览器中测试你的站点的服务。只要提交一个服务请求,该网站就会自动为你运行测试……非常有意思,也是非常强大的辅助工具。
下面是网站的一个截图:
[5] Bubblemark animation test (弹跳小球的动画性能测试——比较各种实现方法)
想知道各种富客户端应用解决方案的性能么?有“好事者”最近就是用各种RIA技术创建了同样的一个测试场景,并集中到了http://bubblemark.com/网站中:
小球将在方框中弹来弹去——很容易直观地看出各种实现方案的优劣之分。目前已经有了如下一些实现方案:
- DHTML
- Silverlight (JavaScript)
- Silverlight (CLR)
- Flash (Flex)
- Flash (Flex) with cacheAsBitmap
- WPF
- Java (Swing)
- Flex Apollo app
- HTML Apollo app
[6] Client Side Script Debugging in ASP.NET (调试ASP.NET客户端JavaScript脚本)
虽然这似乎不是什么新的技术了,不过似乎好多朋友根本不知道如何调试JavaScript。实际上,VS 2005本身已经提供了非常强大(虽然Bug不少)的JavaScript调试支持,可是很多朋友仍旧会看着IE左下角的黄色脚本异常提示图标发愣,不知道如何入手。
如果你也是其中的一员的话,那么这篇文章将会告诉你一些起步的知识。当然,仅仅是起步而已,并没有太过深入的分析,特别是文中没有涉及什么VS脚本调试器中的Bug问题,让人觉得很不爽……
这里为自己做个广告,在我的《ASP.NET AJAX程序设计 第III卷:高级内容》中,将会详细介绍有关客户端脚本调试的知识,敬请期待:)
[7] The JavaScript Dilemma (JavaScript困境)
JavaScript似乎一直就是个颇有争议的东西,ASP.NET MVP Rick Strahl最近也写了一篇长长的文章表达了一下自己的想法。不过他的语言似乎不是那么容易读懂,有兴趣的朋友就看看吧。
[8] Microsoft vs TestDriven.NET - 06 June 2007 (Microsoft对决TestDriven.NET - 06 June 2007)
前两天翻译了一篇有关Microsoft于TestDriven.NET 打架的故事(《TestDriven.NET和Visual Studio Express的纠纷往事》),TestDriven.NET的作者又有了一些新的想法和动向。
看看人家都要上法庭了,下面评论的各位网友还都是心平气和,没一个破口大骂的……让我不知说什么好……无奈?还是羡慕?
这次更新最主要的可能就是官方文档的更新,尤其是对页面的客户端页面生命周期与UpdatePanel客户端生命周期(事实上前者包含了后者)提供了详细的说明和举例。原本我想在3月29日的WebCast中详细讲解的内容,被官方文档覆盖了不少。官方文档越详细,像我这样的技术博客作者可以发挥的余地就小了,还好总是有能够努力的地方。
哎,我要重新想一下WebCast的内容了。不过我在WebCast里会提到一部分UpdatePanel的实现等等,这些属于高级话题。对于这方面有兴趣的朋友可以和我多多交流。:)
至于ScottGu还推荐的其他一些文章,可读性一般。说实话,这些“技术含量”我们绝对能够达到。还有一些文章博客园的朋友们也已经推荐过了,例如Cat Chen曾经推荐过的:How to Build a PageFlakes.com-like Home Page using ASP.NET AJAX。
其实我们完全有能力做的不比他们差,但是我们的确比他们差了。我们最大的弱势在哪里呢?我认为是氛围和语言。我们又该如何解决这样的问题呢?
Orcas主要是VS2005的发布以来的一些反映的Tip的完善,记得在2006年5月份中国微软的谭强来深圳,当时聊起VS2005的相关问题,我给他列了十条,好几条都在这个版本得到实现了,看来Orcas值得期待。还是贴几张图片看看就清楚这些功能是不是也是你所期待的。
在下午的最后一个Session见到Asp.net开发小组的几个成员,主要也是讨论Orcas中的这些功能。Orcas的Pro版本将包含单元测试功能,这个功能vs2005只有VSTS才有,对测试驱动开发的支持,MVC模式的Asp.net的默认实现等,没有透露具体的实现细节,你觉得会怎么设计,我现在的asp.net要做这么大的修改不是一件容易的事。下面贴一张今天出现的asp.net开发组成员照片。

1. windows/temp 目录添加 netword service 帐户;
2. IIS配置下 asp.net 目录添加 netword service 帐户 和 Internet 来宾 帐户;
3. IIS里检测.net framework 版本;
4. 应用程序池 .net framework 版本冲突导致出错的问题, 所以各站点创建各自的应用程序池;
5. 重新注册iis , 找到C:WINDOWSMicrosoft.NETFrameworkv2.0.50727(这里指的是指需要重新注册的framework目录), 运行代码: " aspnet_regiis -i " ;
.net2.0与1.1之比较
“虽然业界对Visual Studio 2005的期望值很高,但它正式推出后,依然远远超出业界的预期。以.NET Framework 2.0为基础的Visual Studio 2005包括微软5年来对.NET 1.0的所有修正。在1.0中还需花费大量时间编写代码的功能,在2.0几乎不需要再写代码或者只需短短几行代码就可以完成。更重要的是,.NET Framework 2.0增添了的不少新类,同时相当多的类被重写,并赋予新的功能,从某种角度来说,2.0更像一种新的语言,由于它的严重“超值”,引来不少开发人员得抱怨。除此以外,微软努力使Visual Studio 2005更适应团队开发,落实了生命周期管理和流程管理,整合了单元测试功能。在2000年我们震惊于.NET 1.0,今天Visual Studio 2005带来的无疑是第二次震撼。”--------天极开发者网络
一、asp.net 2.0的先进性。
asp.net2.0将成为下一代Windows应用程序的基础支柱并集成在Windows Vista之内。
<!--[if !supportLists]-->1、 <!--[endif]-->支持泛型
泛型就是将类型参数化,实现更加广泛的复用。由于减少了装箱和拆箱,泛型对于值类型的对象性能提升明显。
(1) 对于int这样的简单值类型,泛型能够提高2-5倍的速度。数据量越大,越明显。
(2) 对于复杂的值类型,泛型能够提高30%-300%。数据量越大,越明显。
(3) 对于引用(Reference)类型,泛型和传统的方式速度相当。
(4) 泛型是 C# 2.0 的最强大的功能。通过泛型可以定义类型安全的数据结构,而无须使用实际的数据类型。这能够显著提高性能并得到更高质量的代码,因为您可以重用数据处理算法,而无须复制类型特定的代码。
<!--[if !supportLists]-->2、 <!--[endif]-->微软的asp.net ajax(原来叫atlas)与asp.net2.0无缝集成
为了改善用户体验,我们应该在项目中尽可能使用ajax技术来减少页面刷新。
与 .NET 和 Java 平台下其它 AJAX 框架相比,微软的asp.net ajax框架最大的亮点就在于与 ASP.NET 现有机制的无缝融合。通过 VS.NET 集成开发环境,使用者可以在对 js 和 AJAX 不甚了解的情况下,以非常自然的方式使用到最先进的技术。此外直接在 js 一级提供 WebService 的调用支持,也大大降低了对 ws 技术的使用门槛。而 ASP.NET 中一直引以为豪的数据绑定等技术,也可以在 Altas 中无缝得到支持,让现有投资能够最大限度得到保护。从这些意义上来说,虽然 Altas 在 AJAX 理念上没有太多突破,但不失为一个强大且实用的 AJAX 框架,非常符合 MS 在技术运用上的一贯原则。
传统的 WEB 应用程序模型是这样工作的:用户的界面操作触发 HTTP 请求,服务器在接收到请求之后进行一些业务逻辑处理,如保存数据等,然后向客户端返回一个 HTML 页面。但这种方式并没有给予用户很好的应用体验,当服务器在处理数据的时候,用户则处于等待的状态,每一步操作都需要等待,太多的等待会使用户越来越没有耐心。而 Ajax 则大不相同,它通过 Ajax 引擎,使得应用过程很自然,操作很流畅,因为其只和服务器交换有用的数据,而页面显示等不必要的数据则不再重新加载,通过适当的Ajax应用达到更好的用户体验而且可以把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担。
ASP.NET AJAX是微软进军跨平台网络功能领域的作品,用于异步JavaScript的网络开发,可以让开发人员开发出更具互动行动网络应用,提高用户个性化水平。ASP.NET AJAX 1.0的主要功能有:异步客户端到服务器网络、服务器端ScriptManager和ScriptManagerProxy控件、客户端Trace类、Timer控件、Selector控件、JavaScript认证等等。
<!--[if !supportLists]-->3、 <!--[endif]-->使用ADO.NET2.0
(1)、新的索引引擎:
在 ADO.NET 2.0 中已经彻底重新编写了用于 DataTable 的索引引擎,并且使其能够更好地针对大型数据集进行伸缩。这会使基本的插入、更新和删除操作变得更加快速,从而使 Fill 和 Merge 操作变得更快。
(2)、流到缓存,缓存到流
对于 ADO.NET 2.0 中的 DataSet 和 DataTable 类的另一个主要增强是,提供了用来消耗 DataReader(将数据加载到 DataTable 中)以及在 DataTable 的内容之上公开 DataReader 的机制。
有时,我们具有(或收到)DataReader 形式的数据,但实际上是希望具有缓存 DataTable 形式的数据。通过新增的 Load 方法,我们可以获得现有的 DataReader,并使用它的内容来填充 DataTable。
有时,我们具有(或收到)缓存形式的数据 (DataTable),并且需要通过 DataReader 类型接口来访问它。通过新增的 GetTableReader 方法,我们可以获得现有的 DataTable,并通过 DataReader 接口和语义来访问它。
(3)、很多以前DataSet的方法,现在可以用DataTable直接使用了
大多数 .NET 开发人员都知道 DataTable 本身(没有封装在 DataSet 内部)极为有用,并会利用这一事实。但是,在某些情况下,我们无法通过 DataTable 完成我们希望完成的工作,除非我们首先获得它并将其强行转换为 DataSet。这方面的最突出并且通常令人痛苦的示例是在 DataTable 中读取和写入(加载和保存)XML 数据。在 ADO.NET 1.x 中,我们必须首先将 DataTable 添加到 DataSet 中,只有这样我们才能读取或写入 XML,这是因为完成该工作的方法只能在 DataSet 上使用!
ADO.NET 2.0 的目标之一是使独立的 DataTable 类比在 ADO.NET 1.x 中更为实用和有用。
DataTable 可单独序列化,并且可以在 Web 服务和远程处理方案中使用。
附:ADO.NET 2.0 中的新增 DataSet 功能
http://www.microsoft.com/china/MSDN/library/NetFramework/default.mspx?mfr=true
4、改进的ViewState
ViewState 在 ASP.NET 中有个重要的角色。如果使用恰当,它能够简化页面开发,改进用户与站点的交互。如果置之不理,它能够显著增加站点响应大小,在连接速度慢的情况下,使您的 响应时间更加缓慢。ASP.NET 2.0 的发布带来了 ViewState 机制的一些改进,这使得 ViewState 使用更简单,又不会防碍站点性能。这些改进包括:减少编码数量,采用控件状态从内容中分离出行为状态,以及智能集成数据绑定控件。
5、URL映射
使用这个特性我们可以不安全的浏览器地址映射成另一个我们设定的地址,避免出现安全问题。
<!--[if !supportLists]-->6、 <!--[endif]-->新增加不少的类,同时很多类被重写,或添加新功能
<!--[if !supportLists]-->1、 <!--[endif]-->串口操作
新增System.IO.Ports命名空间,提供了SerialPort类来实现串口操作的功能。
<!--[if !supportLists]-->2、 <!--[endif]-->压缩解压
新增System.IO.Compression命名空间,用来处理常用的文件压缩或解压。
<!--[if !supportLists]-->3、 <!--[endif]-->范型
新增System.Collections.Generic命名空间,提供范型支持。
4、网络处理功能增强
新增System.Net.NetworkInformation命名空间,包含了一大堆类型,里面有一个Ping类,就是来实现ping命令的功能。
5、使用FTP
在System.Net 中看到增加了FtpWebRequest和FtpWebResponse两个类,这次可以直接使用Ftp了,不需要再使用第三方的组件。
6、使用SmtpClient
在System.Net.Mail命名空间中提供了对邮件操作的支持。
7、使用多媒体
在System.Media命名空间中提供了一些处理声音的类,不过好像没有看到支持视频的,要使用还是要调用Media Player的组件。
<!--[if !supportLists]-->7、 <!--[endif]-->用户界面控制
asp.net2.0母版页面(Master Pages),可以实现统一的布局效果,可以对系统布局进行集中控制。
<!--[if !supportLists]-->二、 <!--[endif]-->开发环境比较
除了启动速度慢、占用系统资源较多这个缺点外,Visual Studio 2005与Visual Studio 2003相比在易用性,功能方面有了很大的提高。
<!--[if !supportLists]-->1、 <!--[endif]-->支持代码重构
<!--[if !supportLists]-->2、 <!--[endif]-->支持单元测试,自动生成单元测试代码
(1)对私有方法的单元进行测试
使用 Visual Studio 对公共方法进行单元测试,跟以前 NUnit 一样,都是引用需要的类,然后对公共方法进行测试。
(2)用户界面自动化测试
想必大家对类的单元测试已经比较熟悉,这里我们来看看它提供的另一项更为有趣的测试——用户界面自动化测试。事实上这个测试的本质仍是单元测试,单元测试的各种方法在用户界面测试中仍然可用。
而这些测试只需在需要进行测试的方法上简单地点击鼠标右键,在右键菜单中选择 “创建单元测试”,系统就自动产生了这个方法的单元测试代码。
3、类设计器
使用 Visual Studio 类设计器可以显现类和其他类型的结构,还可以通过可视化表示方法编辑它们的源代码。对类图的更改将直接反映在代码中,且对代码的更改会直接影响设计器的外观。设计器和代码之间的同步关系,使得可视化创建和配置复杂的 CLR 类型变得容易。
类设计器包含一些专门设计的功能,这些功能将有助于重构代码、方便地重命名标识符以及重载方法。您可以自动生成类和结构,并通过自动生成存根可以实现接口。
最后,类设计器也可作为通信工具使用,您可以使用它与同事共享代码库区域。类图可以打印成硬拷贝或另存为图像,以便在 HTML 页或 PowerPoint 演示文稿中显示。
<!--[if !supportLists]-->3、 <!--[endif]-->更多更好用的服务器控件
在ASP.NET 2.0中微软内置了更多控件,在1.x中需要程序员费尽心思才能完成的功能,在2.0中只需要简单的套用这些控件就能完成。
<!--[if !supportLists]-->4、 <!--[endif]-->开发和调试彻底摆脱了虚拟目录
1.x版本的asp.net必须信赖虚拟目录进行调试和运行,现在asp.net2.0版本自带一个 development web server进行调试,省去了配置虚拟目录的麻烦。
三、Visual Studio 2005 team suite介绍
Visual Studio 2005 Team Suite 是 Visual Studio 2005 Team System 的一个组成部分,可为软件开发核心团队中的每个成员提供最全面的、用于软件设计、开发和测试的工具集。此外,Team Suite 还为具有多方面专业技能的团队成员提供了极大的灵活性,使他们可以在同一个熟悉的 Visual Studio 开发环境中快速适应结构设计师、开发人员和测试人员的工作。Team Suite 还基于microsoft使用了多年的工具为您提供了用于创建世界一流软件的新功能。当将 Team Suite 与microsoft Visual Studio 2005 Team Foundation Server 一起使用时,Team Suite 可以更好地加强团队的沟通和协作,并可为项目的利益相关方提供有关软件开发过程的、前所未有的透明性。
VS2005采用软件开发生命周期,作为企业在选择信息系统发展方法论(System Development Methodology)时的标准流程,其特征是将开发流程区分为几个连续阶段(3个~20个不等),标示着不同的系统发展成果,实作时则配合专门的技术 角色(分析师、架构师、开发人员、测试人员与项目经理等),目的是容易管理、分层负责与确保软件质量。VS2005则在软件开发生命周期中定义出区分架构 师(Architect)、开发人员(Developer)、测试人员(Tester)与项目经理(Project Manager),并将软件依角色区分为3种版本:Team Architect、Team Developer、Team Tester等,项目经理的权责则包含在Excel或Project上,可与Team System整合。
此外,新的HTML设计器将提供:
- 分割界面(Split View)的支持 (同时将HTML源码和所见即所得设计模式打开的能力)
- 无比丰富的CSS支持 (CSS属性窗口,CSS继承图示器,CSS预览,以及CSS管理器)
- 极大改进的视图转换性能 (从源码模式转换成HTML设计模式将会瞬时完成)
- 对源码视图内控件设计器的支持 (属性构造器,事件接通(wire-up)以及向导将会在源码视图内正常工作)
- 更丰富的标尺(ruler)和布局支持 (更棒的是,它们的值将自动储存在外部的CSS文件中)
- 对内嵌母板页的设计器支持
下面是一张示范多个新功能的屏幕截图:

Visual Studio Orcas的2007年1月CTP已经可以下载了,下载地址是
http://www.microsoft.com/downloads/details.aspx?familyid=1ff0b35d-0c4a-40b4-915a-5331e11c39e6&displaylang=en。
奇怪的是,Visual Studio Orcas的这个CTP居然是用RAR格式压缩的,而不是微软自己的CAB。
另外,Internet Explorer Developer Toolbar也发布了 Beta 3版本,下载地址是http://www.microsoft.com/downloads/details.aspx?familyid=E59C3964-672D-4511-BB3E-2D5E1DB91038&displaylang=en
从文件的版本号来看,Visual Studio 2005 SP1看起来并未更新Visual C++相关的merge module,用Visual Studio 2005 SP1编译的C++应用程序或者DLL在没有安装Visual C++ 2005 SP1再发布文件vcredist.exe的计算机上无法加载。解决的一个办法是再发布vcredist.exe(包含在Visual Studio Professional和以上版本中,默认安装在C:Program FilesMicrosoft Visual Studio 8VCredist下)。
随着Office System 2007的发布,微软公司的新一代企业业务平台变得前所未有的强大。Office相关开发也正逐渐变得炙手可热。为了帮助开发者更好地了解并基于Office System 2007进行开发,微软公司将发布一系列有关Office System 2007的参考文档以及相关辅助软件。
微软公司发布了如下三个与Office System 2007相关的软件和参考文档:
[1] 2007 Office System Document: Compliance Features in the 2007 Microsoft Office System
这篇洋洋洒洒的67页的文档全面介绍了Office System 2007的适应性以及扩展性能力。每一个应用了Office System 2007的企业都将会有它自己的个性化、需要定制的需求。这份文档就将告诉我们Office System 2007开发者什么样的需求是能够实现的,应该怎样实现等相关内容。文档份为如下几大部分:
- Introduction
- An Overview of Regulatory Compliance
- The 2007 Microsoft Office System Products
- Compliance Capabilities in the 2007 Microsoft Office System
- Compliance Extensibility Opportunities
- Development Tools for Extending Office and Windows SharePoint Services
- Summary
- Appendix I: Resources
- Appendix II: References
如果你打算定制出一套自己的Office System 2007系统,那么这份文档绝对不容错过。
[2] 2007 Office System Document: Lists of Control IDs
Office System 2007的UI中引入了一个新东西——Ribbon。虽然对于这个Ribbon,使用者仁者见仁,众说纷纭,不过作为开发者,我们还是有必要赶上发展的脚步。Ribbon这个东西相关的开发也设计得独具匠心,具体内容就不详细说了,有兴趣的朋友可以先参考一下这篇MSDN文档:Customizing the Office (2007) Ribbon User Interface for Developers (Part 1 of 3) 。
微软公司发布的这个软件其实是一个自解压的压缩文件,解压后将得到24个Excel文件,其中分别列出了Office System 2007系列软件中使用的内建Ribbon的ID,方便我们开发时参考。
下图就显示了Word中内建的部分Ribbon的ID:
[3] 2007 Office System Sample: Open XML File Format Code Snippets for Visual Studio 2005
不得不承认,随着Office System 2007的发布,Office开发变得更加简化,提供的API也更加丰富。不过由于Office System 2007本身的复杂性,对于初学者来说,掌握Office System 2007开发仍旧不是一件容易的事情。甚至对于一些最常用功能的实现都无所适从。
微软公司发布的这个Visual Studio 2005的Code Snippets集合就提供了一系列关于Office System 2007开发中经常用到的功能的代码片断。关于Visual Studio 2005的Code Snippets,其实就是一系列常用的代码片断,可以看作是一种代码级别的复用。这里不再多谈Code Snippets,如果你还不是很了解这个强大功能,请参考这篇MSDN文章:How to: Manage Code Snippets。
下面就是在Visual Studio 2005中使用该Code Snippets时的界面:
如上图所示,选择了“Excel: Get sheet info”之后,Code Snippets将自动插入如下一大段代码:
public struct SheetInfo
{public string SheetName;
public string SheetType;
public SheetInfo(string SheetName, string SheetType)
{ this.SheetName = SheetName; this.SheetType = SheetType;}
}
public List<SheetInfo> XLGetSheetInfo(string fileName)
{ // Return a generic list containing info about all the sheets. const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
// Fill this collection with a list of all the sheets List<SheetInfo> sheets = new List<SheetInfo>(); using (Package xlPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read)) { // Get the main document part (workbook.xml).foreach (System.IO.Packaging.PackageRelationship relationship in xlPackage.GetRelationshipsByType(documentRelationshipType))
{ // There should only be one document part in the package. Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
PackagePart documentPart = xlPackage.GetPart(documentUri);
// Load the contents of the workbook, which is all you // need to retrieve the names and types of the sheets: XmlDocument doc = new XmlDocument();doc.Load(documentPart.GetStream());
// Create a NamespaceManager to handle the default namespace, // and create a prefix for the default namespace: XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable); nsManager.AddNamespace("default", doc.DocumentElement.NamespaceURI); // Loop through all the nodes, retrieving the information // about each sheet:foreach (System.Xml.XmlNode node in doc.SelectNodes("//default:sheets/default:sheet", nsManager))
{string sheetName = string.Empty;
string sheetType = "worksheet";
sheetName = node.Attributes["name"].Value; XmlAttribute typeAttr = node.Attributes["type"];if (typeAttr != null)
{sheetType = typeAttr.Value;
}
sheets.Add(new SheetInfo(sheetName, sheetType));}
// There's only one document part. break;}
}
return sheets;}
我们既可以直接使用这些已经生成好了的功能,也可以通过查看代码了解、学习Office System 2007的常用操作。
微软公司昨天发布了一个Windows Communication Foundation (WCF)和Windows CardSpace的示例程序包,内容极为丰富,从最简单的Hello World到复杂的解决方案一应俱全。对于Windows Communication Foundation (WCF)和Windows CardSpace这两个新东西而言,这些示例程序无疑就是最好的学习资源。
这是部分目录截图:
顺便简单介绍一下这两个东西:
Windows Communication Foundation (WCF)(开发代号:Indigo)是微软公司在.NET 3.0下的SOA框架,它也在微软公司的规划中占有非常重要的位置。无论是在组织内部还是组织之间,应用程序通信都是现代软件的基本功能,.NET Framework 3.0 用WCF以SOA的方式提供了程序之间沟通的渠道。下面是官方网站上的介绍:
The Windows Communication Foundation (previously codenamed "Indigo") is Microsoft's unified framework for building secure, reliable, transacted, and interoperable distributed applications.
关于Windows Communication Foundation (WCF),还有如下资源也不错:
- Windows Communication Foundation官方网站: http://wcf.netfx3.com/
- Bruce Zhang的《WCF之旅》系列
- 这个PPT也不错,适合快速了解一下:http://wcf.netfx3.com/files/folders/6680/download.aspx
Windows CardSpace(开发代号:InfoCard)是微软公司新一代的统一数字身份标识控件,旨在解决现今网络上各种身份认证的复杂性、不安全性等问题。这是官方网站上的介绍:
Windows CardSpace enables users to provide their digital identities in a familiar, secure and easy way. In the physical world we use business cards, credit cards and membership cards. Online with CardSpace we use a variety of virtual cards to identify ourselves, each retrieving data from an identity provider. Don't struggle with usernames and passwords, just choose an information card!
ASP.NET 2.0 引入了一系列可以改善数据访问的新工具,包括几个数据源和数据绑定控件。新增种类的数据源控件可以消除 ASP.NET 1.x 中要求的大量重复性代码。例如,您可以很容易地将 SQL 语句或存储过程与数据源控件相关联,并且将它们绑定到数据绑定控件。更令人感到印象深刻的是,通过 ObjectDataSource 控件可以简化开发和减少代码,并且仍然可以在 n 层体系结构的不同层中抽象业务和数据访问逻辑。
在 .NET 问世以前,用传统的 ASP 生成数据网格通常需要编写大量的代码,以便在遍历 ADO 记录集的同时即时生成 HTML 表。ASP.NET 1.x 通过允许您将基于 XML 的 DataSet 绑定到 ASP.NET DataGrid 控件,从而使该类型的开发变得更加容易。这就减少了生成网格所必需的代码。但是,传统的 ASP 和 ASP.NET 1.x 都要求代码实现分页、排序、编辑和行选择功能。通过 ASP.NET 2.0 中的改进功能,可以显著减少这些代码的数量,以产生带有完整分页、排序和编辑功能并填充了数据的网格。
在这一期的 Data Points 中,我将首先演示通过 ASP.NET 2.0 并使用 SqlDataSource 和一些新的数据绑定控件开发 Web 应用程序是多么容易。请注意,我在此使用的是 Beta 1 版本。
大多数企业应用程序都是在多层体系结构之上生成的,该体系结构有一个用于存放业务逻辑的中间层,以及一个使用一个或多个后端数据库的数据访问层。我将讨论 ObjectDataSource 可以多么理想地与现有的多层组件集成。通过将 ObjectDataSource 控件链接到业务对象,您可以充分利用现有的多层体系结构来生成完善的 Web UI,并且能够显著减少代码。 ObjectDataSource 控件还包含一些特殊的属性,使您可以绑定到 ASP.NET 2.0 和 ADO.NET 2.0 中新近增强的强类型 DataSet 和数据组件。 ASP.NET 2.0 中的其他新功能和改进包括新增的双向绑定表达式、增强的缓存,以及几个新增的可以数据绑定到新的数据源控件的 ASP.NET 2.0 控件。
数据绑定控件
要使用数据源控件,必须具有一个用来将它们绑定到的数据绑定控件。在 ASP.NET 2.0 中有几个新的数据绑定控件,包括 GridView、DetailsView 和 FormView 控件。如果您喜欢 ASP.NET 1.x DataGrid 控件,那么您也会喜欢 ASP.NET 2.0 GridView 控件。GridView 在本质上类似于 DataGrid,因为它可以绑定到新的数据源控件,并且可以用来实现排序、编辑和分页 — 它们需要的代码都比 DataGrid 少得多(有关 GridView 的详细信息,请参阅 Dino Esposito 在 MSDN®Magazine 的 2004 年 8 月刊中发表的文章)。
要将 GridView 绑定到数据源控件,需要将 GridView 的 DataSourceID 属性设置为数据源控件的 ID。还可以设置 GridView 的其他几个属性来增强外观和用户交互(我将在稍后的示例中加以演示):
<asp:GridView ID="gvwOrders" Runat="server"
DataSourceID="sdsOrdersDataSource"
AutoGenerateColumns="True">
其他控件(例如,DropDownList)也可以绑定到数据源控件。例如,DropDownList 控件可以绑定到检索雇员列表的 SqlDataSource 控件。雇员的全名可以显示在 DropDownList 中,而 EmployeeID 可以作为控件的基础数据值字段绑定到该控件。以下示例定义了一个 DropDownList,它将显示可供选择的客户名称的列表。客户数据被绑定到一个名为 sdsCustomerDataSource 的 SqlDataSource 控件,该控件可获得客户的 CompanyName 和 CustomerID 字段的列表:
<asp:DropDownList ID="ddlCustomers" Runat="server" AutoPostBack="True"
DataSourceID="sdsCustomersDataSource"
DataTextField="CompanyName"
DataValueField="CustomerID">
</asp:DropDownList>
在 ASP.NET 2.0 中,将控件绑定到数据源控件非常简单,并且不需要任何处于代码隐藏中的代码。但是,如果您愿意,仍然可以编写代码以显式绑定到控件。实际上,数据绑定控件的数据源和 DataMember 属性与 ASP.NET 1.x 相比已经得到了改进。
数据源控件
在 ASP.NET 2.0 中有几个新的数据源控件,例如,SqlDataSource、ObjectDataSource、XmlDataSource、AccessDataSource 和 SiteMapDataSource(如图 1 所示)。它们全都可以用来从它们各自类型的数据源中检索数据,并且可以绑定到各种数据绑定控件。数据源控件减少了为检索和绑定数据甚至对数据进行排序、分页或编辑而需要编写的自定义代码的数量。
每个数据源控件都具有类似的属性,以便可以与其各自的数据源进行交互。生成 SiteMapDataSource 和 XmlDataSource 是为了检索分层数据,而生成其他数据源控件是为了检索带有列和行的基于集合的数据。
专门生成 AccessDataSource 以便从 Access 数据库中检索数据。SqlDataSource 听起来好像只能使用 SQL Server?,但实际情况不是这样的。它实际上可以用来从任何 OLE DB 或符合 ODBC 的数据源中检索数据。
命令类型和参数
SqlDataSource 控件具有四个命令属性,您可以设置这些属性以告诉 SqlDataSource 如何获得、插入、更新和删除它的数据。可以将 SelectCommand 属性设置为 SQL 语句或存储过程。在任何一种情况下,都可以根据需要传入参数。InsertCommand、UpdateCommand 和 DeleteCommand 属性用于告诉 SqlDataSource 使用哪些 SQL 语句(或存储过程)来修改基础数据库中的数据。图 2 中的代码示例显示了一个 SqlDataSource,它将它的 SelectCommand 和 UpdateCommand 属性设置为参数化的 SQL 语句。请注意,UpdateParameters 使用 Parameter 元素来指示要用于参数的字段的名称和数据类型。在将 GridView 绑定到该 SqlDataSource 以后,这些 UpdateParameters 值就被绑定到受影响行的具有相同名称的列。
您自己对此进行试验的最简单方式是,在 Visual Studio? 2005 中创建一个 Web 窗体,连接到服务器资源管理器窗口中的本地 SQL Server Northwind 数据库,然后将一个表拖到该 Web 窗体。这会自动创建一个 SqlDataSource 控件以及一个 GridView。Visual Studio 会自动将 SqlDataSource 控件的 ProviderName 和 ConnectionString 属性设置为 SQL Server Northwind 数据库。而且,所有四个命令属性都将被设置为适当的 SQL 语句。然后,您为编辑该 Web 窗体而必须完成的所有工作就是,使用智能标记来选中“Enable Editing”复选框(参见图 3)。

图 3 GridView设置
数据源控件还可以使用来自其他控件的参数。例如,数据源控件可以检索给定客户的所有订单。在这种情况下,CustomerID 可以是传递给 SqlDataSource 控件的 SelectCommand 属性的 SQL 语句或存储过程的参数。还可以从其他控件(例如,DropDownList)检索 CustomerID,并将其直接传递到 SqlDataSource 控件的 SQL SelectCommand 中。
您可以将控件的值直接链接到 SqlDataSource 控件的任一 SQL 语句(SelectCommand、InsertCommand、UpdateCommand 或 DeleteCommand)的参数,还可以指定究竟要将控件的哪个属性用于该参数。例如,如果您在上一个示例中不需要 DropDownList 的默认属性,而是需要它的 DataTextField,则可以将 ControlParameter 的 PropertyName 属性设置为 DataTextField。
除了 ControlParameter 以外,还可以将其他参数类型用于数据源控件。如果您要使用新的 ASP.NET 个性化功能,则可以使用 ProfileParameter 从配置文件对象中检索参数的值。接下来,还有几个从标准 Request 对象的集合中检索它们的数据的参数对象类型。例如,CookieParameter 可以用来从 Cookie 中检索参数的值。QueryStringParameter 从任意请求字符串变量中获得它的值,而 FormParameter 从 HTML 窗体的输入字段中获得它的值。最后,SessionParameter 可以用来从会话变量中检索它的值。这些类型的参数为数据源控件提供了多个有关如何设置它们的参数值的选项。
SqlDataSource 示例
既然我已经完成了概述,那么我将对使用 SqlDataSource 和 ObjectDataSource 来检索和修改数据进行一下对比。SqlDataSource 控件(它使用 ADO.NET 2.0 DbProviderFactory 对象)具有将它直接链接到 OLE DB 或 ODBC 数据源的属性。当加载包含链接到 SqlDataSource 的数据绑定控件的 ASP.NET 页时,SqlDataSource 直接与基础数据库进行通信。因而,SqlDataSourceData 源控件不与现有的业务对象集成。
为了查看 SqlDataSource 是如何操作的,让我们先观察一下 Orders_SDS.aspx 页(参见图 4)。有一个 DropDownList 控件,它绑定到一个从 Northwind 数据库中检索客户列表的 SqlDataSource 源控件。

图 4 通过 SqlDataSource 检索客户
还有另外一个名为 sdsOrdersDataSource 的 SqlDataSource,它用于检索选定客户的所有订单。图 5 中的代码(摘自 Orders_SDS.aspx — 它可在下载中得到)显示了两个 SqlDataSource 控件和这个 DropDownList。请注意,sdsOrdersDataSource SqlDataSource 控件使用 DropDownList 的选定值作为其存储过程的参数(prGet_Orders 的参数)。
ProviderName 和 ConnectionString 属性的组合告诉 SqlDataSource 控件从哪个数据存储中获得数据。尽管这些属性使 SqlDataSource 成为检索和修改数据的简单解决方案,但遗憾的是,它们在表示层的 ASPX 文件中公开了数据库连接字符串以及 SQL 语句或存储过程。这通常不是一个好主意。将该数据以加密形式存储在配置储存库(如配置文件或注册表)中要安全得多。
图 4 显示了编辑模式下的 Orders_SDS.aspx 页。分页由 GridView 自动实现(通过将 GridView AllowPaging 属性设置为 true,并将 PageSize 属性设置为期望的大小,如 10)。这将告诉网格将其中的行分页,并且在“下一页”或“上一页”链接被单击时自动重新加载网格和页。GridView 使用 TextBox 控件显示选定行的可编辑列。数据绑定列是通过 asp:BoundField 或 TemplateField 元素定义的。通过设置 DataField 属性,可以将 BoundField 绑定到 GridView 的关联数据源:
<asp:BoundField HeaderText="ShipCity" DataField="ShipCity"
SortExpression="ShipCity"></asp:BoundField>
这将告诉 GridView 控件,当它处于查看模式时,应该在 span 元素中显示 ShipCity 值。当 GridView 处于编辑模式时,选定行中的这一列将在适当的 HTML 元素中显示。在这种情况下,HTML 元素为 TextBox,因为它是一个字符串值。该元素是基于绑定列的数据类型选择的。例如,如果该列在 SQL Server 中被定义为位,则将使用 CheckBox 控件在编辑模式下显示该列。
TemplateField 元素在绑定列的行为方式方面提供了更大的灵活性。请观察以下摘自 Orders_SDS.aspx 页的代码示例:
<asp:TemplateField SortExpression="OrderDate" HeaderText="OrderDate">
<ItemTemplate>
<asp:Label ID="lblOrderDate_Item" Runat="server"
Text='<%# Bind("OrderDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtOrderDate_Edit" Runat="server"
Text='<%# Bind("OrderDate", "{0:d}") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
当 GridView 处于查看模式时,它使用 TemplateColumn 在 Label 控件中显示 OrderDate 列;当 GridView 处于编辑模式时,它使用 TemplateColumn 在 TextBox 控件中显示 OrderDate 列。您还可以使用 FooterTemplate 来告诉 Template 列在页脚中以不同的方式显示该列。还可以使用 HeaderTemplate、AlternatingItemTemplate 甚至 InsertItemTemplate。还请注意 ASP.NET 2.0 中引入的简化的绑定语法。OrderDate 的值是通过调用 Bind 表达式并向它传递 GridView 的关联数据源中列的名称和一个可选的数据格式字符串表达式来设置的。在该示例中,我使用了表示短日期的数据格式字符串。这些属性都可以通过可借助于 Visual Studio 2005 中的新增智能标记功能访问的属性来轻松设置(参见图 6)。

图 6模板列属性
ObjectDataSource
GridView 和其他数据绑定控件的最出色的功能之一是,在设置了它们以后,只需更改单个属性,就可以将它们绑定到 ObjectDataSource 控件或 SqlDataSource 控件。例如,您必须完成的所有工作就是创建一个新的 ObjectDataSource 控件,并将 GridView 的 DataSourceID 属性更改为这个新的 ObjectDataSource 控件的 ID。
与 SqlDataSource 不同的是,ObjectDataSource 控件使您可以从 ASPX 页和表示层中抽象出特定于数据库的设置,并将它们移至多层体系结构中的较低层(参见图 7)。例如,SqlDataSource 控件的 ConnectionString、ProviderName 和 SelectCommand 属性在 ObjectDataSource 控件中不存在。相反,它们被替换为告诉 ObjectDataSource 控件实例化哪个业务类以及使用哪个方法来检索或修改数据的其他属性。

图 7 层
要设置 ObjectDataSource 控件以访问另一个层的业务类及其方法,必须首先将 ObjectDataSource 控件的 TypeName 属性设置为该业务类的名称(如 TypeName="MSDN2005Jan_BLL.Orders")。然后,将 SelectMethod 属性设置为该业务类中将用来检索数据源数据的方法的名称。该业务类的方法必须返回一个可枚举的列表,例如,集合、数组、DataSet 或 DataReader。为了让该方案能够工作,ObjectDataSource 必须能够执行指定的方法。如果它是静态方法,则不需要完成任何特殊的工作。如果该方法是实例方法,则 ObjectDataSource 必须能够创建该类的实例。要达到该目的,最简单的方法是将该业务类编写为包含默认的构造函数。另外,还可以处理 ObjectDataSource 的 ObjectCreating 事件,它使您可以用所需的任何构造函数来实例化该对象,然后将该对象实例传递给数据源控件。
图 8 中的代码示例(摘自同样包含在下载中的 Orders.aspx)显示了两个 ObjectDataSource 控件(它们替换了上一个示例中使用的两个 SqlDataSouce 控件)。odsOrdersDataSource 使用 MSDN2005Jan_BLL.Orders 类和它的 GetData 方法来检索它的订单列表。在该示例中,Orders 类中的 GetData 方法只是创建名为 OrdersDataSet 的强类型 DataSet 的实例及其相关的名为 OrdersTableAdapter 的适配器。然后,它调用 Fill 方法并返回强类型的 DataSet:
public OrdersDataSet GetData(string CustomerID)
{
OrdersDataSet oDs = new OrdersDataSet();
OrdersTableAdapter oDa = new OrdersTableAdapter();
oDa.Fill(oDs, CustomerID);
return oDs;
}
请注意,GetData 方法还接受由 ObjectDataSource 控件的 SelectParameter 属性传入的 CustomerID 参数。UpdateData 方法的参数也是从图 8中所示的 UpdateParameters 属性所指示的 ObjectDataSource 传入的。以下为 Orders 类的 UpdateData 方法的签名:
public void UpdateData(int OrderID, DateTime OrderDate,
string ShipCity, string ShipCountry)
UpdateData 方法的参数的名称和数据类型必须与 ObjectDataSource 控件中更新参数的名称和数据类型相匹配。数据源控件不能使用批处理更新,因此不能一次性地将多个行传递给更新方法。相反,必须将每个值作为单个参数传递给更新方法。除了 SelectMethod 和 UpdateMethod 属性以外,ObjectDataSource 控件还具有 DeleteMethod 和 InsertMethod 属性。
增强的强类型DataSet
上一个示例演示了如何将 GridView 绑定到 ObjectDataSource 控件以链接到业务层的类,因此您可以通过该类的方法来检索和更新数据。如果您具有现有的业务层逻辑和多层体系结构,则该示例可以很好地工作。它还可以调用 Web 服务客户端代理的方法,或其他任何遵循类和方法要求的引用类的方法。
我故意将上个示例的一个方面延迟到现在才加以讨论,那就是强类型 DataSet。使用 Visual Studio 2005 中的向导,您还可以直接在类型化的 DataSet 类中定义方法,以便选择、插入、更新和删除数据。因而,您可以避免直接在业务层或数据访问层中编写任何 ADO.NET 代码,而是使用向导直接将 ADO.NET 逻辑添加到类型化的 DataSet 中。
您不必检索类型化的 DataSet,但是在这种情况下它是有价值的 — 这要归功于它的一些新的增强功能。类型化的 DataSet 创建了一个默认的 Fill 方法,该方法被追加到类型化 DataSet 的定义中的 TableAdapter 类。可以将这一可选的 TableAdapter 类设置为存储连接字符串以及存储过程或 SQL 语句,以便在数据库中选择、更新、插入和删除记录。

图 9 Orders DataSet
类型化的 DataSet 还允许您创建自定义的方法,以便检索和修改数据。在 Orders DataSet(如图 9 所示)中,我基于 prGet_Orders 存储过程创建了一个类型化的 DataSet。然后,通过数据组件查询配置向导,我向 OrdersTableAdapter 中添加了两个自定义方法:GetData 和 UpdateData。这些方法是在与类型化 DataSet 的 XSD 相关联的类文件内部定义的;在该示例中,我的文件名为 OrdersDataSet.Designer.cs。如果您想了解详细信息,可以打开这个自动生成的文件(但是您不应当修改它,因为如果该文件被重新生成,则您的更改将被改写)并查看自定义的 GetData 和 Update 方法以及为类型化 DataSet 创建的所有标准代码。如果您运行示例页 Orders2.aspx,则它会直接绑定到上述自定义方法。这可以显著减少您为中间层手动编写的代码数量。
其他数据源控件细节
现在我们已经完成了讨论,如果您知道数据源控件还可以通过一系列属性来公开缓存功能,则可能会很感兴趣。通过将 EnableCaching 设置为 true 并将 CacheDuration 设置为很多秒,数据将在缓存中存储相应的时间。还可以将 CacheExpirationPolicy 属性设置为 Absolute 或 Sliding。Absolute 是默认值,它告诉缓存在加载后立即开始倒计时直至过期。Sliding 策略告诉缓存在缓存数据每次被访问时重置过期倒计时。在您要加载的数据不是非常容易改变的情况下,缓存技术可以帮助优化应用程序。例如,在加载省、市甚至产品类别的 DropDownList 的数据源控件中使用缓存是有好处的,因为这些数据不会频繁更改。
ObjectDataSource 控件包装了挂钩到业务对象以调用业务方法的代码。它还与数据绑定控件(例如,GridView)协同工作,以执行分页、排序以及在 ASP.NET 1.x 中必须手动编码的数据更改。
小结
ASP.NET 2.0 中的改进(尤其是在数据源和数据绑定控件领域中的改进)显著减少了产生带有完整分页、排序和编辑功能并填充了数据的网格所需的代码数量。尽管数据源控件消除了过去必须手动编写的大量代码,但您仍然可以编写代码以便与数据源控件进行交互。您不仅可以只通过指指点点来创建数据驱动的 Web 页,而且还可以编写代码来使用数据源控件的事件,例如,Selected、Selecting、Updated 或 Updating 事件。
简介
在 Microsoft ASP.NET 2.0 Framework 中,数据库访问得到了极大的简化。利用全新的 SqlDataSource 控件,您无需编写一行代码就可以选择、更新、插入和删除数据库数据。
生成简单的应用程序时,SqlDataSource 控件是一个很好的选择。如果您需要迅速生成一个使用户可以显示和编辑数据库记录的 Web 页,使用 SqlDataSource 控件在几分钟之内就能完成此工作。
例如,我自己就曾计时生成了这么一个页面。通过结合使用 SqlDataSource 控件与 GridView 控件,我在 1 分 15秒 内就能生成一个用于显示 Northwind Products 数据库表的内容的页面。就有这么快!
但是,SqlDataSource 控件存在一个问题。如果您使用 SqlDataSource 控件,那您就是在做不太妙的事情。SqlDataSource 控件的缺点在于它迫使您将用户界面层与业务逻辑层混合在一起。任何应用程序架构师都会告诉您:混合多个层的行为是不可取的。
生成严格意义上的多层 Web 应用程序时,您应该具有清晰的用户界面层、业务逻辑层和数据访问层。仅仅由于 SqlDataSource 控件的强制而在用户界面层引用 SQL 语句或存储过程是完全错误的。
那么为什么您要关心这些东西呢?不错,在很多情况下,您不必在意。如果您正在创建一个简单的 Web 应用程序,完全可以使用 SqlDataSource 控件。例如,如果您需要生成一个由单独页面组成的应用程序来显示数据库的表的内容,那么将应用程序划分为多个应用程序层就很不明智。
遗憾的是(如果您已经为此“交过学费”,则会感到幸运),并非所有的 Web 应用程序都很简单。应用程序达到一定的复杂程度之后,如果将其划分为多个应用程序层,则生成和维护它们就更轻松。
将应用程序划分为多个应用程序层有很多优点。如果您有一个清晰的业务逻辑层,就能够创建一个可以从多个页面调用的方法库。换句话说,创建一个清晰的业务逻辑层提升了代码重用。此外,创建清晰而独立的应用程序层使得应用程序更易于修改。例如,清晰的层次使您无需修改数据访问代码就可以修改用户界面。
如果您需要使用 ASP.NET Framework 生成多层 Web 应用程序,那么您可以使用 ASP.NET 2.0 Framework 所引入的另一个新控件:ObjectDataSource 控件ObjectDataSource 控件使您可将诸如 GridView 和 DropDownList 这样的用户界面控件绑定到一个中间层组件。
这篇文章的主题就是 ObjectDataSource 控件。在这篇文章中,您将学习如何使用此控件来显示和编辑数据库数据。我们还将讨论如何结合使用 ObjectDataSource 控件和 SqlDataSource 控件以简化数据库访问。
使用 ObjectDataSource 控件显示数据
我们在这里设想您需要创建一个用于显示 Products 数据库表的内容的 Web 页面。再进一步设想您的某个现有业务组件包含了一种用于检索此数据的方法。
例如,清单 1 中的组件包含了一个名为 GetProducts 的方法,此方法返回一个 DataReader 来表示 Products 数据库表的内容。
清单 1: ProductInfo.cs (C#)
using System;
using System.Data;
using System.Data.SqlClient;
public class ProductInfo
{
const string conString =
"Server=localhost;Trusted_Connection=true;Database=Northwind";
public static SqlDataReader GetProducts()
{
SqlConnection con = new SqlConnection(conString);
string selectString = "SELECT * FROM Products";
SqlCommand cmd = new SqlCommand(selectString, con);
con.Open();
SqlDataReader dtr =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dtr;
}
}
清单 1: ProductInfo.vb (Visual Basic .NET)
Imports System.Data
Imports System.Data.SqlClient
Public Class ProductInfo
Const conString As String = _
"Server=localhost;Trusted_Connection=true;Database=Northwind"
Public Function GetProducts() As SqlDataReader
Dim con As New SqlConnection(conString)
Dim selectString As String = "SELECT * FROM Products"
Dim cmd As New SqlCommand(selectString, con)
con.Open()
Dim dtr As SqlDataReader = _
cmd.ExecuteReader(CommandBehavior.CloseConnection)
Return dtr
End Function
End Class
如果您将清单 1 中包含的这个类添加到应用程序的 Code 目录中,那么 ASP.NET Framework 将自动编译这个类。换句话说,只要向 Code 目录添加了这个类,就可以立即在 ASP.NET 页中使用它。
我们将使用 GridView 控件(在 ASP.NET 2.0 Framework 中替换了 DataGrid 控件)来显示由 GetProducts 方法返回的数据库记录。清单 2 中的 ASP.NET 页包含了一个绑定到 ObjectDataSource 控件的 GridView。
清单 2: ShowProducts.aspx
<html>
<head>
<title>Show Products</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
Runat="Server" />
<asp:ObjectDataSource
ID="ObjectDataSource1"
TypeName="ProductInfo"
SelectMethod="GetProducts"
Runat="Server" />
</form>
</body>
</html>
清单 2 中声明的 ObjectDataSource 控件包含两个重要的属性。TypeName 属性指示类名,而 SelectMethod 属性指示在选择数据时要在此类上调用的方法名。
在清单 2 中,ObjectDataSource 控件用于调用 ProductInfo 类上的 GetProducts 方法。由于 GridView 控件绑定到了 ObjectDataSource 控件上,因此通过 GridView 控件的 DataSourceID 属性,GridView 控件即可显示产品列表(请参见图 1)。

图 1. 使用 ObjectDataSource 控件显示产品
您可以结合使用 ObjectDataSource 控件与任何标准的 ASP.NET 数据绑定控件(例如,GridView、DropDownList、TreeView 和 Repeater 控件)。ObjectDataSource 控件使您能够将任何标准控件绑定到组件。
SelectMethod 可以引用静态方法(在 Visual Basic .NET 中共享)或实例方法。如果您使用的是实例方法,则 ObjectDataSource 控件在调用这个方法前,会自动创建此组件的一个实例。在完成方法调用后,将自动销毁此组件。
结合使用参数与 ObjectDataSource 控件
您可以将参数与使用 ObjectDataSource 控件调用的方法一起使用。当您调用某方法时,如果需要将某些值(例如,控件属性或查询字符串的值)传递给此方法,则这种方式就非常有用。
在前一节中,我们使用 ObjectDataSource 控件创建了一个页面,用于显示来自 Products 数据库表的所有记录。在本节中,我们将修改此页面,以便允许用户从 DropDownList 控件(请参见图 2)选择产品类别。

图 2. 从 DropDownList 选择产品类别
清单 3 包含了修改后的 ProductInfo 组件。
清单 3: ProductInfo2.cs (C#)
using System;
using System.Data;
using System.Data.SqlClient;
public class ProductInfo2
{
const string conString =
"Server=localhost;Trusted_Connection=true;Database=Northwind";
public SqlDataReader GetProducts(string category)
{
SqlConnection con = new SqlConnection(conString);
string selectString = "SELECT Products.* " +
"FROM Products INNER JOIN Categories " +
"ON Products.CategoryID=Categories.CategoryId " +
"WHERE CategoryName=@CategoryName";
SqlCommand cmd = new SqlCommand(selectString, con);
cmd.Parameters.AddWithValue("@CategoryName", category);
con.Open();
SqlDataReader dtr =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dtr;
}
}
清单 3: ProductInfo2.vb (Visual Basic .NET)
Imports System.Data
Imports System.Data.SqlClient
Public Class ProductInfo2
Const conString As String = _
"Server=localhost;Trusted_Connection=true;Database=Northwind"
Public Function GetProducts(ByVal category As String) _
As SqlDataReader
Dim con As New SqlConnection(conString)
Dim selectString As String = "SELECT Products.* " &
"FROM Products INNER JOIN Categories " & _
"ON Products.CategoryID=Categories.CategoryId " & _
"WHERE CategoryName=@CategoryName"
Dim cmd As New SqlCommand(selectString, con)
cmd.Parameters.AddWithValue("@CategoryName", category)
con.Open()
Dim dtr As SqlDataReader = _
cmd.ExecuteReader(CommandBehavior.CloseConnection)
Return dtr
End Function
End Class
清单 3 中经过修改的 ProductInfo 组件包含了一个经过修改的 GetProducts 方法,此方法包含了一个用于类别名的参数。这个参数用于限制从数据库返回的产品。
清单 4 包含了 DropDownList、GridView 和ObjectDataSource 控件,使您可以选择要显示的不同类别的产品。
清单 4: ShowProducts2.aspx
<html>
<head>
<title>Show Products</title>
</head>
<body>
<form id="form1" runat="server">
<asp:DropDownList
id="DropCategories"
AutoPostBack="true"
Runat="Server">
<asp:ListItem Value="Beverages" />
<asp:ListItem Value="Seafood" />
</asp:DropDownList>
<br /><br />
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
Runat="Server" />
<asp:ObjectDataSource
ID="ObjectDataSource1"
TypeName="ProductInfo2"
SelectMethod="GetProducts"
Runat="Server">
<SelectParameters>
<asp:ControlParameter
Name="category"
ControlID="DropCategories" />
</SelectParameters>
</asp:ObjectDataSource>
</form>
</body>
</html>
从清单 4 的 DropDownList 控件选择新类别时,GridView 控件将自动地只显示来自选定类别的产品。
请注意,清单 4 中的 ObjectDataSource 控件包含了一个 SelectParameters 元素。这个元素列出了调用由 ObjectDataSource 控件的 SelectMethod 属性指定的方法时使用的所有参数。在本例中,SelectedParameters 元素包含了一个名为 category 的单个参数。这个参数表示来自 DropCategoriesDropDownList 控件的 SelectedValue 属性的值。
使用 ObjectDataSource 控件编辑数据
ObjectDataSource 控件包含 4 个重要属性:SelectMethod 属性、UpdateMethod 属性、InsertMethod 属性和 DeleteMethod 属性。综合利用这些属性,您能够指定执行标准数据库操作所需的所有方法。
例如,您可以使用 ObjectDataSource 控件来编辑数据库数据。在清单 5 中,修改后的 ProductInfo 类包含了一个新的 UpdateProduct 和 DeleteProduct 方法。
清单 5: ProductInfo3.cs (C#)
using System;
using System.Data;
using System.Data.SqlClient;
public class ProductInfo3
{
const string conString =
"Server=localhost;Trusted_Connection=true;Database=Northwind";
public static SqlDataReader GetProducts()
{
SqlConnection con = new SqlConnection(conString);
string selectString = "SELECT ProductId,ProductName, " +
"UnitPrice FROM Products ORDER BY ProductId";
SqlCommand cmd = new SqlCommand(selectString, con);
con.Open();
SqlDataReader dtr =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dtr;
}
public static void UpdateProduct(int original_productId,
string productName, decimal unitPrice)
{
SqlConnection con = new SqlConnection(conString);
string updateString = "UPDATE Products SET " +
"ProductName=@ProductName,UnitPrice=@UnitPrice " +
"WHERE ProductID=@ProductID";
SqlCommand cmd = new SqlCommand(updateString, con);
cmd.Parameters.AddWithValue("@ProductName", productName);
cmd.Parameters.AddWithValue("@UnitPrice", unitPrice);
cmd.Parameters.AddWithValue("@ProductId", original_productId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
public static void DeleteProduct(int original_productId)
{
SqlConnection con = new SqlConnection(conString);
string deleteString = "DELETE Products " +
"WHERE ProductID=@ProductID";
SqlCommand cmd = new SqlCommand(deleteString, con);
cmd.Parameters.AddWithValue("@ProductId", original_productId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
清单 5: ProductInfo3.vb (Visual Basic .NET)
Imports System.Data
Imports System.Data.SqlClient
Public Class ProductInfo3
Const conString As String = _
"Server=localhost;Trusted_Connection=true;Database=Northwind"
Public Shared Function GetProducts() As SqlDataReader
Dim con As New SqlConnection(conString)
Dim selectString As String = "SELECT ProductId, " & _
"ProductName,UnitPrice FROM Products ORDER BY ProductId"
Dim cmd As New SqlCommand(selectString, con)
con.Open()
Dim dtr As SqlDataReader = _
cmd.ExecuteReader(CommandBehavior.CloseConnection)
Return dtr
End Function
Public Shared Sub UpdateProduct(ByVal original_productId _
As Integer, ByVal productName As String, _
ByVal unitPrice As Decimal)
Dim con As New SqlConnection(conString)
Dim updateString As String = "UPDATE Products " & _
"SET ProductName=@ProductName,UnitPrice=@UnitPrice " & _
"WHERE ProductID=@ProductID"
Dim cmd As New SqlCommand(updateString, con)
cmd.Parameters.AddWithValue("@ProductName", productName)
cmd.Parameters.AddWithValue("@UnitPrice", unitPrice)
cmd.Parameters.AddWithValue("@ProductId", original_productId)
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Sub
Public Shared Sub DeleteProduct(ByVal original_productId _
As Integer)
Dim con As New SqlConnection(conString)
Dim deleteString As String = "DELETE Products " & _
"WHERE ProductID=@ProductID"
Dim cmd As New SqlCommand(deleteString, con)
cmd.Parameters.AddWithValue("@ProductId", original_productId)
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Sub
End Class
您可以将这个修改过的 ProductInfo 类与清单 6 中包含的ObjectDataSource 控件一起使用,以编辑 Products 数据库表的内容。
清单 6: ShowProducts3.aspx
<html>
<head>
<title>Show Products</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
DataKeyNames="ProductId"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
Runat="Server">
<Columns>
<asp:BoundField
DataField="ProductName"/>
<asp:BoundField
DataField="UnitPrice"
DataFormatString="{0:c}"/>
</Columns>
</asp:GridView>
<asp:ObjectDataSource
ID="ObjectDataSource1"
TypeName="ProductInfo3"
SelectMethod="GetProducts"
UpdateMethod="UpdateProduct"
DeleteMethod="DeleteProduct"
Runat="Server">
<UpdateParameters>
<asp:Parameter
Name="original_productId"
Type="Int32" />
<asp:Parameter
Name="productName" />
<asp:Parameter
Name="unitPrice"
Type="Decimal"/>
</UpdateParameters>
</asp:ObjectDataSource>
</form>
</body>
</html>
在清单 6 中,GridView 控件显示了ProductName 和 UnitPrice 这两个列的值。由于 GridView 控件的 AutoGenerateEditButton 和 AutoGenerateDeleteButton 属性均设置为值 True,GridView 将自动生成用于编辑和删除产品行的用户界面(请参见图 3)。

图 3. 使用 ObjectDataSource 控件编辑数据
当您单击 Update 链接更新产品时,ObjectDataSource 控件将调用 UpdateProduct 方法。请注意,ObjectDataSource 控件在其 UpdateParameters 元素中列出了传递给 UpdateProduct 方法的参数。
有一个参数需要额外进行讨论。我们需要将被更新的行的 ProductID 列的值传递给 UpdateProduct 方法由于没有在 GridView 中显示 ProductID 列,我们必须将 ProductID 列分配给 GridView 控件的 DataKeyNames 属性。这个列的名称变为 original_productId,而不是 productId,因为我们正在向 update 方法传递 ProductID 列的未编辑版本。
如果您单击 Delete 链接,ObjectDataSource 控件将调用 DeleteProduct 方法。由于 GridView 控件的 DataKeyNames 属性具有值 ProductId,因此会再次将一个名为 original_productId 的参数自动传递给 DeleteProduct 方法。
结合使用 ObjectDataSource 控件和 SqlDataSource 控件
到目前为止,我们已经将 ObjectDataSource 控件与使用 SqlDataReader 对象的组件一起使用,以便检索数据库数据。这里还有另一种选择。即不在组件内使用 SqlDataReader 或 DataSet 等 ADO.NET 对象,而是在组件中使用 SqlDataSource 控件。
您可以在组件中使用 SqlDataSource 控件的这一事实似乎很奇怪。通常,您不在组件中使用控件,因为控件一般具有可视化表示形式,而且控件参与页面执行生命周期。而 DataSource 控件在这一点上有些特殊。
如果您希望简化组件中的数据库访问代码,您可以在此组件中使用 SqlDataSource 控件。清单 7 展示了这种方式。
清单 7: ProductInfo4.cs (C#)
using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
public class ProductInfo4
{
const string conString =
"Server=localhost;Trusted_Connection=true;Database=Northwind";
public static IEnumerable GetProducts()
{
string selectString = "SELECT * FROM Products";
SqlDataSource dsrc = new SqlDataSource(conString,
selectString);
dsrc.DataSourceMode = SqlDataSourceMode.DataSet;
return dsrc.Select(DataSourceSelectArguments.Empty);
}
}
清单 7: ProductInfo4.vb (Visual Basic .NET)
Imports System.Collections
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class ProductInfo4
Const conString As String = _
"Server=localhost;Trusted_Connection=true;Database=Northwind"
Public Shared Function GetProducts() As IEnumerable
Dim selectString As String = "SELECT * FROM Products"
Dim dsrc As New SqlDataSource(conString, selectString)
dsrc.DataSourceMode = SqlDataSourceMode.DataSet
Return dsrc.Select(DataSourceSelectArguments.Empty)
End Function
End Class
在清单 7 中,我们实例化了 SqlDataSource 控件的一个新实例。SqlDataSource 的构造函数接受了一个用于数据库连接字符串的参数和一个用于与 select 命令一起使用的命令文本的参数。接着,将 DataSourceMode 属性的值设为 DataSet(这里的另一个选项是 DataReader)。最后,在 SqlDataSource 控件的实例上调用 Select 方法,并返回表示来自 Products 数据库表的所有记录的 DataView。
您可以将清单 7 中的 ProductInfo 类与清单 8 中包含的 ObjectDataSource 控件一起使用:
清单 8: ShowProducts4.aspx
<html>
<head>
<title>Show Products</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
Runat="Server" />
<asp:ObjectDataSource
ID="ObjectDataSource1"
TypeName="ProductInfo4"
SelectMethod="GetProducts"
Runat="Server" />
</form>
</body>
</html>
在清单 8 中,GridView 控件绑定到了 ObjectDataSource 控件上。而 ObjectDataSource 控件又调用了 ProductInfo4 类的 GetProducts 方法,以检索由 GridView 显示的数据。最后,GetProducts 方法使用 SqlDataSource 控件检索数据库数据。
小结
ASP.NET 2.0 Framework 极大地简化了数据库访问,使您可以更轻松地生成简单和复杂的 ASP.NET 应用程序。如果您需要生成一个简单的数据库驱动 Web 应用程序,那么您可以使用新的 SqlDataSource 控件。如果您需要生成一个更为复杂的应用程序或示例,您可以在传统的 3 层应用程序中使用 ObjectDataSource 控件。
ObjectDataSource 控件使您能够继续在数据驱动页面中使用中间层组件。其主要优势在于使您无需编写任何代码即可绑定到一个组件,从而极大简化了您的用户界面。使用 ObjectDataSource 控件,我可以在 3 分钟 20 秒的时间内生成一个可以显示 Product 数据库表的组件和页面。尽管这种方式花的时间比使用 SqlDataSource 控件长,但我感觉这样做时页面的体系结构要好得多。
先看一个现象:
如果你有这样的一个WebService 方法:
public void myTest(System.Collections.Specialized.NameValueCollection col)
{
.....
}
那你在请求这个WebService 方法的时候,会收到如下异常:
To be XML serializable, types which inherit from ICollection must have an implementation of Add(System.String) at all levels of their inheritance hierarchy. System.Collections.Specialized.NameValueCollection does not implement Add(System.String).
详细的错误发生点如下:
[InvalidOperationException: To be XML serializable, types which inherit from ICollection must have an implementation of Add(System.String) at all levels of their inheritance hierarchy.
System.Collections.Specialized.NameValueCollection does not implement Add(System.String).]
System.Xml.Serialization.TypeScope.GetDefaultIndexer(Type type, String memberInfo) +849
System.Xml.Serialization.TypeScope.ImportTypeDesc(Type type, MemberInfo memberInfo, Boolean directReference) +857
System.Xml.Serialization.TypeScope.GetTypeDesc(Type type, MemberInfo source, Boolean directReference, Boolean throwOnError) +135
System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflec tionMember xmlReflectionMember, String ns, XmlReflectionMember[] xmlReflectionMembers, Boolean rpc, Boolean openModel) +78
System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlRefle ctionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel) +280
这是因为对 ICollection 接口的类进行序列化的一些特殊要求:
XmlSerializer 可以以不同方式处理实现 IEnumerable 或 ICollection 的类,条件是 这些类满足某些要求,如下所示。
1、实现 IEnumerable 的类必须实现带单个参数的公共 Add 方法。Add 方法的参数必须与 从 GetEnumerator 方法返回的 IEnumerator.Current 属性所返回的类型一致(多态) 。
2、除实现 IEnumerable 外还实现 ICollection 的类(如 CollectionBase)必须有一个 值为整数的公共 Item 索引属性(在 C# 中为索引器),并且必须有一个整数类型的公 共 Count 属性。传递给 Add 方法的参数必须与从 Item 属性返回的类型相同或与该类 型的某个基的类型相同。
3、对于实现 ICollection 的类,要序列化的值将从索引的 Item 属性检索,而不是通过 调用 GetEnumerator 来检索。另外,除返回另一个集合类(实现 ICollection 的集合 类)的公共字段之外,将不序列化其他公共字段和属性。
ICollection 接口的类要可以被序列化,该类必须包含 Add 方法和要序列化的 Item 属性(C# 索引器)。
上面的WebService 例子出现异常是因为:
NameValueCollection 并不直接实现 ICollection 接口。相反,NameValueCollection 扩展 NameObjectCollectionBase。这样,就会实现 ICollection 接口,并且在 NameValueCollection 类中不实现重载 Add(system.string) 方法。
在使用 XMLSerializer 时,XmlSerializer 尝试将 NameValueCollection 序列化或反序列化 为一般 ICollection。因此,它查找默认的 Add(System.String)。如果没有 Add(system.String) 方法,就会发生异常。
参考资料:
PRB:使用 XmlSerializer 序列化 NameValueCollection 对象时出 现“System.InvalidOperationException”错误
http://support.microsoft.com/default.aspx/kb/814187/zh-cn?spid=548&sid=304
序列化实现 ICollection 接口的类
http://msdn2.microsoft.com/zh-cn/library/58a18dwa.aspx
http://www.codecomments.com/archive321-2006-2-823224.html
http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_ 21585935.html
AJAXWorld杂志主编 Dion Hinchcliffe 不久前发表了《你需要知道的有关AJAX的七件事情(Seven Things You Need to Know About AJAX)》一文。大意如下,
1。浏览器并不适合AJAX。第一个认真的AJAX项目才开始一周,你会发现Ajax 几乎已把浏览器推向其极限。事实是,没有强有力的第三方开发工具,清晰地设计任何规模的 Javascript 软件都需要训练有素和艰苦努力才成。在多个浏览器里调试Ajax应用麻烦透顶,想要做些认真的后台或多线程更需要你使出浑身解数,特别是你想结合那些用了数目有限的计时器的其他的组件。好消息是,简单的AJAX,(譬如点缀些DHTML),比大规模的AJAX要轻松得多了。但做好准备,一旦你的应用规模加倍,随时扩大开发和测试的努力。
2。你不需要你想象中的那么多 Web 服务。我原以为走Ajax这条路需要开发许多新的Web 服务来提供数据和存储。事实上,我发现许许多多项目满足于HTML scraping或使用老式的HTTP POST。这使得尝试 Ajax 开发容易之极,可以重用任何现有的后端HTTP服务,而不是转向SOAP或REST/WOA等复杂的服务。虽然这大概会导致糟糕的架构级的选择,但这也使逐步转化到Ajax 毫不费力,简直自然之极,虽然因此造成的以后的头痛大概是难以避免的。
3。Ajax比传统Web设计和开发更棘手。HTML用户界面规范的丢失,几乎无限制的隐藏功能的可能性,编程手法创建页面元素,以及Ajax 方式的其他固有的特性把我们所知的Web设计和开发方式都扔出门外去了。 Web 设计师必须深刻理解DOM,Javascript和CSS的能力,对浏览器如何显示图像,如何布局,以及显示各种元素要有深刻理解。开发人员发现测试既困难又枯燥。虽然工具在不断地,全面地改进,但要让整个工业积累出行之有效的最佳实践,模式和实用知识,要花几年时间呢。在此要高度赞扬一下象雅虎的Bill Scott这样的业界人士,赞赏他们通过推动类似雅虎UI设计模式库这样的东西,尝试解决这里提到的许多问题,极大地推进了业界的最高工艺水平。结论是,Ajax开发,起码是目前,与传统的Web开发相比要花更多的时间,同时要求更高的技能。
4。Ajax 工具和组件仍在涌现,现今还没有明显的领先者。虽然Dojo火爆出场,但竞争远未结束。譬如,Dojo框架本身的版本还是0.3 (注:Dojo 0.4已发行)。紧随其后的种种工具,框架和组件库还有很多。虽然OpenAjax 旨在使得众多产品相互合作,大多数的开发人员只会掌握这其中的2-3个,然后就一直用这几个产品了。在目前的情形下,过早定死在某个特定的产品,一般来说不是个好主意。创新,竞争,和市场的领先地位此起彼伏,尚无定数。同时,一定要去看一下script.aculo.us,Prototype,Google Web Toolkit,Yahoo! UI Library, JackBe,Zapatec,Bindows, Nexaweb,General Interface,Backbase,ActiveWidgets,以及 微软的Atlas。
5。优秀的Ajax 程序员很是难找。Zimbra的Scott Dietzen最近感慨找到好的Ajax人才之难。但参考上述第3点,建造复杂的Ajax 应用要求的计算机技能要远比Web设计技能多得多。我发现有经验的程序员不太喜欢Javascript编程和调试。这种情形不会持久,但也要过几年才行。
6。必须积极地对付浏览器模型对Ajax的限制。虽然最后的结果会非常值得 ,但象任何技术, Ajax远非完美,它也有几个弱点。一个是它会违反现有的Web模型,譬如,加书签,后退按钮等等。幸运的是, 象Brad Neuberg这样的有识之士对此类问题已有方案,只要你愿意花力气,理解恢复此类功能的重要性。Ajax 也缺乏桌面软件的的很多强处,譬如能离线运行,访问本地硬盘存储等,但Flash 的本地存储和即将发行的Apollo平台能应付这类问题。
7。Ajax 只是成功RIA策略的一个因素。如果你想让你的在线应用实现范围很广的功能,那么你必须将类似Flex,OpenLaszlo, 以及WPF/E等这样的RIA平台放在考虑范围之内,特别是在想支持象音像这样丰富的媒体的情形下,而Ajax对此几乎无能为力。Ajax 会日益对这些平台造成威胁,特别是在后端服务器提供对服务器端push,Web 服务,企业环境等支持的情形下。
I'd classify the Microsoft Ajax Library as having:
- Moderate DOM Traversal, only basic get by ID - no apparent DOM creation methods.
- Acceptable DOM Events.
- Good Ajax Support.
- No Animation Support.(注:其实ASP.NET AJAX有动画支持)
....Even with just the better DOM support the library would already be ahead of Prototype in directly useful functionality....
Brad Abrams还指出了几个有意思的地方,
- 基本的 XmlHttp 抽象和 JavaScript 语言扩展大家都做得差不多了,有区别也不是很大。真正的竞争将在UI widgets层次上展开,有意思的是,这些UI widgets 是不大容易从一个框架移植到另一个框架的,在接下来的6个月至1年内,框架的与众不同之处将渐渐展现出来。
- 有人指出“Better is Simpler”,应该是指AJAX的易用性,surface area小,而且更加直观。
- 在客户端和服务器端之间的平衡。AJAX 模型把焦点从一个项目UI模型转移到更着重于应用层次服务的集成。ASP.NET 和Atlas的结合是绝配。
- 性能随应用场景而变,没有绝对的答案,应该测量的是用户对性能的感觉(user perception of performance),而不是raw throughput。
- 在用户点击提交按钮前把数据传回服务器,不纯是一个技术性的问题,而是用户的感知模型的问题,因为用户根据以往体验的理解是,在点击提交前,数据是不应该记录的。
说到在SharePoint Server中整合其他应用系统,其实是一个挺复杂的问题,需要考量多方面的问题,并在各种选项中做出最佳的选择。在这里,将SharePoint Server在整合这方面的方法比较系统的描述一下,希望对大家有帮助。这里面说的SharePoint Server是泛指,并不针对特定的SharePoint Portal Server 2003或Office SharePoint Server 2007。
看到这里,可能会有朋友问了,整合应用系统?这不是BizTalk Server应该干的活吗?是的,EAI(企业应用集成)正是BizTalk Server的强项。但是首先,BizTalk Server更擅长的在应用层对各个应用和系统进行整合,也就是说,BizTalk Server和各个系统打交道的方式大多数是通过这些系统的各种API,而在很多场合我们除了在应用层需要对各个系统进行整合之外,我们还希望在界面上对各个应用也能有整合,也即展现层的整合,展现层的整合能够让用户在一个统一的界面上访问和操作多个应用系统,看到各个系统中的信息。对于展现层的整合,我们同样需要有一个基于Web的平台来干这个,而这就是SharePoint Server的强项了。
其次,很多时候我们可能不一定需要BizTalk Server这样的“重型武器”,在文章的后面我们会看到,只有在某些复杂的场合,更确切的说,是客户已经有了较多的应用,而且各个应用间的确有互联、整合、集成的需求,才有BizTalk Server的用武之地。
一般,我们将SharePoint Server的应用整合方式分为下面的四种(下面的图片摘自PPT,所以非常抱歉比较大):
第一种:基于Web界面的整合
这种方式简单来说,就是直接把其他系统的Web界面直接拿过来,放到SharePoint Server的页面上去,让用户可以在SharePoint这一个界面里面能够访问到其他系统。
这种方式是几种整合方式中最简单的一种,但是简单并不意味着不实用,有的时候,基于Web界面的整合可能就是最好,也是最省事的方法。使用这个方法有一个先决条件,就是要整合的应用必须有Web展现,否则就无从谈起了,幸好现在是一个Web大行其道的年代,几乎大部分企业应用系统都是通过Web方式展现给客户的。
SharePoint Portal Server 2003中已经提供了两个现成的Web Part,来帮助我们完成基于Web界面的整合。第一个是网页查看器Web Part,给它一个URL,它能把指定的页面以IFrame的方式直接嵌到SharePoint页面中。另外一个是网页截取器Web Part,它能让我们指定一个网页中的一个部分,然后它会自动把这个部分截取下来,显示在SharePoint页面中,而且我们还能指定一个更新周期,这个Web Part会隔一段时间就检测指定的网页是否发生的变化,然后更新要显示的网页部分块。
当然,除了使用SharePoint自带的Web Part之外,我们还可以用自己的方式,来进行这种进行Web界面的整合。只要你的方法基本原理是将另外一个应用系统的Web界面弄到SharePoint里面,那么就应该属于这第一种方法。
使用基于Web界面的整合可能遇到的一大挑战就是单点登录(SSO),因为要整合的那个Web应用很可能是需要登录后才能访问的,而用户显然不希望在SharePoint里面查看另外一个应用系统的信息时,还需要再登录一次,所以我们需要帮助用户来自动完成这个登录过程。
第二种:基于数据源的整合
由于某种原因,比如要整合的系统根本就没有Web展现,或者SSO不好做,难以整合,同时用户也只需要能够在SharePoint里面看到那个系统里面的数据而已,并不需要做什么交互操作(比如,客户只需要看到上个月的销售数据报表,或者客户信息表),而且我们也可以直接访问到要整合的系统的数据库,那么用这第二种方法也许是一个不错的主意。
基于数据源的整合,就是直接去连接要整合系统的数据库,然后利用某些Web Part将一个表、或者多个表的数据直接展现出来。SharePoint提供了现成了Web Part,允许我们使用ODBC方式去连接任何数据库,然后把数据展现在SharePoint页面上。当然,自己做一个定制的展现数据库数据的Web Part也并不是一件难事。
这种方法的一个重要好处是,你根本不需要考虑那个应用系统是怎么做的、如何做的、接口是什么,只要你能访问到它的数据库,就能搞定。
基于数据源的整合有一个重要的前提条件,就是你知道要整合的系统数据库在哪、如何访问,以及了解它的数据库结构(数据字典),就是说,你要清楚的知道,应该将哪个Database的哪个Table的哪些Field的数据展现出来,才是客户想看到的数据。
第三种:点对点的整合
点对点的整合是指,让开发人员开发出定制的Web Part,在Web Part的代码里面,访问要整合的系统的特定的API(可能是各种类型的,比如Web Service,或者对象模型),以在Web Part里面来完成某件任务。由于可能需要针对每一个应用系统,甚至应用系统中的每一项功能,来开发出一个对应的Web Part,所以这种方法被成为点对点的方法。
点对点整合可以带来最大的灵活性和最大的功能性,因为只要其他的应用系统带有相应的接口,我们就可以在Web Part里面完成任意的功能:从其他应用系统中获取数据、与其他应用系统进行交互操作,等等。
但这种方法也有自己的前提。首先,要整合的应用系统必须有相应的接口,如果面对一个根本就没有考虑过被第三方访问,根本没有设计任何API的应用,那就没法子了(这种类型的应用系统并不少见!)。其次,如果有API,Web Part开发人员还需要了解这些API,知道怎么调用,调用哪个才是自己需要的,有很多应用系统是非常复杂的,提供了庞大繁杂的API,如果不熟悉这些应用系统的接口,学习成本还是不小的。
点对点整合的一个典型例子就是专门访问SAP系统的SAP iView Web Part Toolkit,另外,对于如何将SAP整合到SharePoint里面,这个网站是非常有价值的:www.microsoft-sap.com/interop.aspx。
第四种:应用集成方式的整合
终于,在面对最复杂的场景,我们要用上BizTalk Server这样的EAI服务器了。如果我们需要整合多个系统,比如在一个Web Part里面能够操作多个系统按照某个流程完成某项任务,那么使用这种整合方式应该是最合适的了。
在这种方式里面,我们需要有一台专门的应用集成与整合服务器,通过它与各个应用系统打交道,在它上面完成业务流程的编制和创建,然后通过在Web Part中调用这个应用集成与整合服务器的接口,来完成整合功能。
OK,现在,我就将最常见的四种整合方式介绍完了,最后,我想让大家了解一下Office SharePoint Server 2007中提供的一个新的,用于进行应用整合的组件:Business Data Catalog。
上面的图片(同样摘自某张PPT,所以再次抱歉图片较大)展示了BDC的整体架构和作用。BDC提供了一种中间层,在这个中间层里面,我们可以定义出数据的Metadata,然后BDC会根据Metadata,从后台的应用系统中将相应的数据抽取上来,以供SharePoint Server使用。
在BDC中,我们首先可以定义Application,Application基本对应于应用系统,然后,我们可以在一个Application中定义多个Entity(实体,比如“客户”、“员工”),基于Entity,我们可以再定义它的属性、方法、动作。将这些Metadata定义好了之后,BDC就能够透过两种方式根据Metadata从后端应用系统中得到这些Entity的数据:一种是使用ADO.NET直接去访问数据库,一种是去访问后端应用系统的Web Service接口。
BDC从后端应用系统中将定义好的数据抽取上来之后,SharePoint Server 2007中有自带的Web Part能够直接显示这些数据,而且可以对这些数据进行过滤查询等等,另外,SharePoint Server 2007的搜索引擎可以将BDC数据作为内容源进行检索,这样,SharePoint Server 2007无形中就实现了对业务系统的数据搜索功能了。当然,BDC也提供了完善的API,让我们能够在自己的应用或者Web Part里面访问BDC中抽取出来的数据,或者将更新的数据写回到后端应用系统中。
BDC的出现,大大扩展了SharePoint Server对第三方应用系统的整合能力,通过BDC,大大简化了对后端业务系统中的数据访问、操作、搜索。关于BDC的更详细信息,请参考SharePoint Server 2007 SDK里面的相关内容。
在AJAX世界里处理错误经常会相当棘手,特别当AJAX回调正在进行,应用中客户端和服务器端的编码混合着运行的时候。在最新的版本中,ASP.NET AJAX中的 <asp:updatepanel> 控件现在拥有更健壮的处理错误和报告错误的特性可以为你所用。具体来说,
1) 你现在可以在 <asp:scriptmanager> 控件上处理OnAsyncPostBackError事件,来捕捉和/或修改在服务器端处理AJAX postback回调时发生的错误消息。
2) 你现在可以在 <asp:scriptmanager> 控件上设置AllowCustomErrors属性,启动标准的 ASP.NET 自定义出错支持,在错误反生时,即使这个错误是在AJAX postback 中发生的,可以把用户自动重新定向到一个错误页面。
3) 你现在也可以在页面上选择处理客户端的JavaScript事件来拦截任何从服务器端发回的错误消息,从而来执行自定义的客户端行为。譬如,不是跳出一个消息对话框,而是把错误消息输出到一个格式好看的 <div> 区去。
我们使用 FileSystemObject 对象创建文件时候,由于这是个早期版本,你想创建一个utf-8编码的文件,或者读取时候,很容易出现乱码。这时候,你可以使用 ADODB.Stream 对象:
下面的代码就是一个简单的vbScript例子,
把C:Logs 目录下的所有文件和并到一个568.txt 文件:
Function LoadFile(Path)
Dim Stm2
Set Stm2 = CreateObject("ADODB.Stream")
Stm2.Type = 2
Stm2.Mode = 3
Stm2.Open
Stm2.LoadFromFile Path
'Stm2.Charset = "UTF-8"
'Stm2.Charset = "Unicode"
Stm2.Charset = "GB2312"
Stm2.position = 0
LoadFile = Stm2.ReadText
Stm2.Close
Set Stm2 = nothing
End Function
Dim Stm1
Set Stm1 = CreateObject("ADODB.Stream")
Stm1.Type = 2
Stm1.Open
'Stm1.Charset = "UTF-8"
Stm1.Charset = "Unicode"
Stm1.Position = Stm1.Size
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder("C:Logs")
Set fc = f.Files
For Each f1 in fc
'Wscript.Echo f1.name
Message = LoadFile("C:Logs"&f1.name)
'Wscript.Echo Message
Stm1.WriteText Message
Next
set fc = nothing
set f = nothing
set fso = nothing
Stm1.SaveToFile "568.txt",2
Stm1.Close
set Stm1 = nothing
注意:你需要根据你自己对应文件夹下文件的编码,设置ADODB.Stream 对象的 Charset 属性。
我就是在这个代码例子基础上,把我对数据库的每个表、存储过程定义的sql,合并为一个文件,这样,我可以在每次需要发布的时候,执行一边这个脚本,就自动产生需要发布的sql语句集合了。
附:
FileSystemObject 对象的创建文件说明
object.CreateTextFile(filename[, overwrite[, unicode]])
unicode 可选项。Boolean 值,指明文件是否以 Unicode 或 ASCII 文件方式创建。如果文件作为 Unicode 文件创建,则值为 true ,如果作为 ASCII 文件创建,则为 false。如果忽略,则假定为 ASCII 文件。
尽管BHO被给与了太多的权限,以至于很多反恶意软件对BHO倍加关注,但是很多BHO也是很有用的,例如Google ToolBar和Internet Explorer Developer Toolbar。在Windows XP SP2中,微软在IE中加入了加载项管理器来管理包含BHO在内的浏览器扩展。
微软在1999年1月发布了一篇名为Browser Helper Objects: The Browser the Way You Want It的文章,同时在微软知识库中也提供了一个示例IEHelper,这使得编写BHO的难度大大降低,但是这也使得有缺陷的BHO的数量增加。甚至在最近这篇文章Building Browser Helper Objects with Visual Studio 2005的示例代码中,也有着一些缺陷,但是这篇文章也详尽地阐述了编写BHO需要注意的事项,编写BHO的程序员应该去看一看。
文中的RGS应该从
HKLM {
SOFTWARE {
Microsoft {
Windows {
CurrentVersion {
Explorer {
'Browser Helper Objects' {
ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s
'HelloWorldBHO' {
val 'NoExplorer' = d '1'
}
}
}
}
}
}
}
}
改为
HKLM {
NoRemove SOFTWARE {
NoRemove Microsoft {
NoRemove Windows {
NoRemove CurrentVersion {
NoRemove Explorer {
NoRemove 'Browser Helper Objects' {
ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s
'HelloWorldBHO' {
val 'NoExplorer' = d '1'
}
}
}
}
}
}
}
}
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2,
&LIBID_SHDocVw, 1, 0>
应该改为
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2,
&LIBID_SHDocVw, 1, 1>
If the page has no frames, the event is fired once after the page is ready, but before any script has run.这句话有误,浏览器在下载到BODY内嵌的script标签的时候就会执行脚本。
those that fire DownloadBegin will also fire a corresponding DocumentComplete 这里DocumentComplete 应该是DownloadComplete。
Russ 和 Heidi 开发的这些控件适配器对所有的ASP.NET数据控件(GridView,DataList, DetailsView,FormView等),导航控件(Menu,TreeView),登录控件 (Login,CreateUserWizard, ChangePassword,PasswordRecovery,LoginStatus) 提供了一个基于纯CSS(而不是表格)的显示机制。
控件适配器Beta3的发布
这个星期早些时候,发布了CSS控件适配器的Beta3版本,在其融入了更多的反馈和建议,还添加了许多新特性。下面对几个既新又酷的特性提供了快捷指引:
- 打开 Menu(菜单) 例子,增加你的浏览器的字体大小,在IE里使用查看->文字大小->更大。
- 打开 CreateUserWizard 例子,使用accesskey来导航。如果在Windows下,按 Alt + e 把焦点设置在Email地址文本框里。(在IE里,对密码文本框,你必须同时按下Shift键才能使用对应的accesskey)。
- 试用一下重新设计的 TreeView 例子。展开树的几个节点,选择一个节点造成页面提交。注意到没有,树保持了展开的节点的状态,对被选择的节点做了可见的标记,同时用它的值改动了页面中的内容。
- 玩一下级联复选框(cascading checkboxe)。
- 验证这些页面遵从XHTML 1.1严格标准。
在Office2007中,对于end user最大的改变包括三个:
- 全新的格式栏(Ribbon)用户界面。下拉式菜单几乎被全部取消了,除了留下一个躲藏在左上角的文件(file)菜单。
- 全新的基于xml技术的OpenXML开放式文件格式。
- 处处可见的人性化设计,使学习,操作更加直观,简单。可以快速生成专业效果的文档。
在上面的三个改变中,前两个是最令我担忧的。一个普通用户能否在使用中对这两个改变理解,并适应这种改变呢?
昨天,我在中山市国际酒店做office 2007的演讲。课后有许多客户询问Office 2007文件格式相关的问题,直到今天早上还接到了电话询问。主要问题包括:Office 2007生成的文档,Office 2003和支前版本是否无法打开了?Office 2007生成的很多漂亮的图形,图片效果在Office 2003和之前版本中打开会有怎么样的变化?效果还会保留吗? 为了解释这个文档格式问题,我这里给大家做一些解释。
1,OpenXML。我们知道,在Office 2007中,Word 2007,Excel2007,PowperPoint 2007都采用全新的基于XML技术的文档格式,他们新的文件扩展名已经变为了docx,xlsx,pptx,我们称之为OpenXML.其实,OpenXML文件格式的文件,是一个使用了压缩技术的压缩包。我们完全可以将这个压缩包更名为.zip,然后使用winzip,winrar或者xp直接打开,会发现文件包中其实有很多的文档组成元素。
2,默认情况下,Office 2007保存文件时,Word文档时docx,Excel文档时xlsx,PowerPoint文档是pptx.
3,用户可以使用左上角的文件菜单,采用另存为的方式将Office 2007的文档保存为Office 97-2003兼容格式的文档。这样虽然会损失少量的效果,但是那些仅仅安装了Office 2003和之前版本的用户,可以直接读取,编辑这些文档。
4,用户可以直接选择将Office 2007的文档保存为PDF/XPS格式的文档。该功能也需要使用Office左上角的文件菜单另存为功能。默认情况下,Office 安装时,并没有启用该功能,用户需要回到微软网站下载一个加载项http://www.microsoft.com/downloads/details.aspx?FamilyID=4d951911-3e7e-4ae6-b059-a2e79ed87041&DisplayLang=en,该功能才能启用工作。XPS是微软公司提供的一个类似PDF的文件分享格式。(注意:当前没有简体中文版的加载项,用户下载英文版的加载项可以在中文的Office 2007中使用)
5,如果运行Office 2003和之前版本的用户需要打开Office 2007的OpenXML格式文档,他们需要安装一个叫做Office_2007_beta2 com_pack的文件。
全新的OpenXML具有以下几个有点:
1,开放性。基于XML的文档格式,用户可以直接通过程序自动将数据库或者其他数据源合并到文档中,甚至手工更改文档。整个过程不需要安装office。而且比以前更加的简单。
2,安全性。当文件遭到破坏时,可以实现分块修复。而不至于整个文件无法使用
3,更小的文件Size。文件采用了压缩技术放入到一个压缩包中,如果文件中包含一些未压缩的文档内容。文件大小会比以前有明显的节省。这样更加利于存储和传递分享。
用户、企业在完成Microsoft Office system的部署以后会发现将现有的文件格式与Office Open XML Formats之间进行转换,以及将文档、工作表、演示文稿保存为新的格式都非常容易。将新的文件保存为Office Open XML Formats,只需单击Save命令同时为文件指定保存的格式即可。用户同样可以将Office Word、Office Excel、Office PowerPoint文档的默认存储格式设置为Office Open XML Formats。企业和用户可以将现有的文档统一转化为Office Open XML Formats格式。新的Microsoft Office system应用程序将向后兼容Microsoft Office system的二进制文件格式,所有现存的Microsoft Office system文件都可以在Microsoft Office 2007正式发布的版本中继续使用。
此外,可能由于某些原因用户不想使用新的Office Open XML Formats格式,这时候用户仍然可以将文件保存为Microsoft Office system二进制文件格式。 IT部门可以利用Office Migration Management Technologies(Office移植管理技术)来完成大量的文档格式转换。利用格式转换工具可以快速的将文档自动的转换为全新的Office Open XML Formats,当然我们也可以选择手动的方式来完成转换文档格式的工作(例如,在文件包含宏指令的情况下,我们无法自动完成格式的转换,需要用户去打开、测试、并明确的指定该文档的存储格式)。
最后,为了确保还没有部署Microsoft Office system 2007的用户可以存取、访问Office Open XML Formats格式的文档,Microsoft为以前发布的Microsoft Office system版本提供了一个可以下载的pack,通过它即使没有部署Microsoft Office system 2007的用户仍然可以存取Office Open XML Formats格式的文档。Microsoft所提供的pack将与Office System 应用程序相互兼容。
在研究AJAX时,调试 Javascript 大概是经常的事。看到了 Ziemowit 介绍如何在 VS 2005 里调试 Javascript 的这篇文章,推荐一下:
Debugging client JavaScript in VS 2005
http://www.developerfusion.co.uk/show/5918/
大概步骤如下:
1。在浏览器里启动脚本调试:在IE里菜单 工具->Internet 选项->高级页中,把Disable script debugging (Internet Explorer) 前的勾去掉
2。然后在 VS 2005 里打开你的项目,把你要调试的网页设置为起始页,然后按F5,然后去 VS 2005 菜单 Debug-> Windows ->Script Explorer,VS 2005就会打开脚本管理器,双击其中某个JS文件,该文件将会在主窗口打开,然后你就可以添加断点,。。。。。
这是我在 VS 2005 里调试 ASP.NET AJAX Beta 1 里的MicrosoftAjaxWebForms.js,查看表单是如何提交的:
【更新】aldebaran 在回复里提到了另一种方法,对这种方法感兴趣的话,具体细节参考
Debug Javascript with IE and Visual Studio 2005
http://brennan.offwhite.net/blog/2006/01/23/debug-javascript-with-ie-and-visual-studio-2005/
大概这样,设置完菜单 工具-> Internet选项->高级页里启动脚本调试后,关闭浏览器,重新打开IE,打开想调试的网页,然后去菜单 View->Script Debugger->Break at Next Statement。。。然后在网页中要执行Javascript时,就会跳出一个窗口要你选择脚本调试器。如果你选择VS 2005的话,会有一个小问题,它也许会打开文件选择对话框,要你打开JS源码文件,(显然,在上面这个例子中,我没有这个同名的(带长串查询字符串的)文件),但你可以关闭这个对话框,然后双击脚本管理器的文件名就可以了。(在VS 20005 Team System里,发现有一个问题,当你设置脚本断点时,有时光标会跑到别的地方去。)
SPS2003的数据库迁移应该是一个常见的维护操作。比如,在我们安装SPS2003时,很可能将其使用的SQL Server也一起安装在同一台服务器上,但是随着时间的流逝,SPS2003门户网站里面的内容越来越多,访问量越来越大,SQL Server的负荷也会越来越重。这个时候,SPS管理员就可能需要认真考虑一下是否将SQL Server服务器迁移到另一台性能更好的服务器上。这样,就带来了SPS2003数据库迁移的问题。
微软对于如何将正在运行的SPS2003的数据库进行迁移,有标准的解决方案。简单来说,就是首先使用SPS2003备份和恢复工具将SPS2003门户网站完整的备份下来,然后在SPS2003上删除全部原有门户,然后更新配置数据库到新的SQL Server服务器上,然后使用SPS2003备份和恢复工具来恢复门户网站,这样,门户网站的内容数据库就也迁移到新的SQL Server服务器上了。
除了这个官方解决方案之外,我在这里还看到过一个非官方的方案,很有意思,而且要比官方方案要更简捷一些。我将这个方案整理了出来,您可以直接参考:
1、将SPS使用的三个数据库全部完整备份下来(这三个数据库的名字分别以_Prof, _Serv和_Site结尾)。这个步骤非常非常重要,保存好备份后的文件!!
2、在新的服务器上安装好SQL Server,然后以同样的名字创建那三个数据库,使用SQL Server的恢复数据库功能将备份好的数据库恢复到这台服务器上。注意,备份/恢复数据库的操作,可能并不会将原有的安全权限信息完整复制到新的服务器上,请手工操作,确保新的SQL Server服务器上的安全设置与原有的保持一致。
3、备份好SPS门户网站对应磁盘根目录下的web.config文件。
(以下的步骤会使SPS门户站点暂时不可用,建议干脆暂时停止用户对SPS门户站点的访问)
4、打开SharePoint Portal Server管理中心。
5、进入“指定组件设置数据库服务器”,勾掉“使用与配置数据库相同的服务器”复选框,在下面的“服务器名称”文本框中填入新SQL Server服务器名称,确定。
6、进入“指定内容数据库服务器”,勾掉“使用与配置数据库相同的服务器”复选框,在下面的“服务器名称”文本框中填入新SQL Server服务器名称,确定。
7、进入“列表和管理门户网站”,选择相应的门户网站,删除它,在删除确认页面,勾选“删除所有数据库”。
8、点击管理中心左侧的“Windows SharePoint Services”,进入到WSS管理中心。
9、进入“设置服务器配置数据库”,在“数据库服务器”文本框中填入新的SQL Server服务器的名称,确定。
10、点击左侧的“SharePoint Portal Server”,回到SPS管理中心。
11、进入“配置服务器拓扑结构”,确认在“数据库服务器设置”区域下面的所有数据库服务器设置都使用了新的SQL Server服务器名称,确认在“组件分配”区域下面,Web、搜索、索引、作业这几个服务器角色仍然是使用的当前的Web服务器。点击“关闭”按钮。
12、进入“列表和管理门户网站”,点击“恢复门户网站”,在恢复门户网站页面填入新的SQL Server服务器的名称和其他相关信息,确定。
13、将第3步备份的web.config拷贝回SPS门户网站对应的磁盘根目录下。如果web.config里面有对原来SQL Server服务器的引用,那么将这些引用更新到指向新的SQL Server服务器。
14、打开SPS门户网站,确认数据库迁移已经成功了。在门户网站的新闻区域,可能会增加一条新的新闻列表,把它删除即可。
最后要提醒的是,不管你是使用哪种方案来做数据库迁移,之前一定要先做好备份的两个步骤:第一个步骤是使用SPS2003备份和恢复工具,对整个门户网站进行完整备份,第二个步骤是使用SQL Server的数据库备份来将SPS2003所使用的所有数据库进行完整备份。
授权管理器(AzMan)是 Windows Server (2000、2003、Longhorn Server...)中自带的、能够和AD紧密集成的、供应用程序使用的授权检查引擎,它实现了完整的基于角色的授权管理框架,利用它,可以在应用程序中大大简化与授权有关的代码编写与实现。
在目前版本中,授权策略信息有两种存储方式:
- XML
- 目录(如活动目录-AD或ADAM)
上述两类三种存储方式的适用场景分别如下:
- 简单的小型应用可以直接使用XML,在这种方式中,不用设置/扩展 AD/ADAM 的 Schema,非常方便
- 如果基础域环境不好(如应用程序不便访问DC、存在多个Domain)等情况时,可以使用 ADAM
- 如果基础域环境较好,且应用程序的身份完全与AD集成,最好使用AD
在 Vista 中,AzMan 又增加了一种存储方式:SQL Server,这样对于应用程序来说,又多了一种更实用的选择,而且即然能存在 SQL Server中,估计通过一些手段,这些信息也能存储到其他类型的数据库中,如Access、Oracle等,现在 ASP.NET 2.0中的一些 Provider 不也是公开源代码了,并且实现了其他数据库类型的 Provider 了嘛。
不过,AD/ADAM 具有复制功能,可以方便地实现多个实例之间的目录同步,而SQL Server 不具有此功能,另外 AD/ADAM 在查询方面具有性能优势(AzMan的绝大多数请求是查询),所以到底要使用哪一种存储方式,还是要综合评估。
Sidebar Gadget开发方式
在Windows Vista中提供的Sidebar版本中,我们使用Microsoft HTML引擎来开发Gadget,这包括HTML标签、脚本、图片以及其它相关的特性。Sidebar也提供了丰富的APIs集,使得Gadget中的脚本可以调用Windows中已经安装的ActiveX对象。
Gadget下载
Gadget是使用HTML以及脚本开发完成的,但是这个HTML并非在远程Web服务器上执行。首先,我们需要将Sidebar Gadget从服务器上下载,然后在本地机器上执行。这种过程比较类似于从服务器端下载可执行文件(.exe),然后执行的过程。
Gadget文件本身是一种压缩格式,可以采用的压缩机制包括ZIP方式或者CAB方式。如果使用CAB方式打包,我们为其添加证书,进行数字签名。数字签名工具可以使用Visual Studio 2005中的“Signtool.exe”命令。
只有当用户查看过Gadget提供的相关信息后,Sidebar才开始载入MSHTML控件进行呈现,并且执行脚本代码。
注:以下图片来自于预发行版本的Windows Vista,在未来有可能会有所不同:
图1:带有代码签名的安装对话框
图2:不带有代码签名的安装对话框
由于代码签名需要耗费一定的时间,而且并不普遍,我们并没有强制要求所有的Gadget都必须签名后才可以部署。
HTML 运行时
HTML Gadgets将会遵照Internet Explorer以及域沙盒(Domain sandboxing)的安全设置来执行。不过,因为Gadget类似于其它可执行文件,拥有相似的下载过程以及安装体验。所以HTML运行时给予了Gadget相当的权限来执行,类似于HTML Application(HTA)运行时权限以及本地机器区域的安全配置。
Gadget在其安全配置上,与普通的Web网页有很多不同点。第一点,Gadget可以创建任何已安装的ActiveX对象的实例,因为其被配置为“可以初始化并且脚本访问未被标记为安全的ActiveX”。其次,Gadget也可以访问跨域的数据源,因为只有将不同位置的数据进行相应的集成,Gadget对于开发人员和最终用户才有意义。最后一点特殊的是,在SideBar的HTML页面中禁止下载任何新的ActiveX控件,无论这个ActiveX控件是签名或者未签名的。
User Account Control (UAC) 交互
User Account Control (UAC) 是Windows Vista提供的一个新特性,使用户能够以标准用户权限来运行Windows。如果当前Windows用户是标准用户,那么Sidebar Gadgets也会为标准用户权限来执行,从而避免Gadget做出破坏系统的行为。在UAC审批模式下,即使当前用户是Administrators组中的成员,默认情况下,Gadgets也会为标准用户权限来执行。这样做可以有效阻止Gadget修改系统中受保护的资源。
另外一个我们需要知道的是,虽然其它可执行软件在需要较高权限运行时,会弹出相应的对话框,来要求用户给予完全的Administrator权限。但Sidebar Gadget在此种情况下,不会显示此对话框。不过,通过Gadget来调用的应用程序仍然会显示此对话框,以获得更高权限。
举个例子,如果Gadget试图删掉System32系统目录中的一个文件,虽然此操作会失败,但不会给予最终用户任何提示。失败的原因是由于系统文件无法被标准用户修改。
分级模式交互
IE中的分级模式也会影响SideBar Gadget的执行。IE 7的分级模式可以由父母或者其它监护人模式设置安全浏览以及所执行的一系列策略,比如禁止儿童访问一些成人或者其它非法站点。举例来说,如果分级模式仅允许儿童访问站点A或者B,而Gadget试图与站点C进行通讯,那么将会失败。
Windows Defender 交互
由于Windows Vista中的Windows Defender中的存在,Gadget的下载会更加安全。如果允许,Windows Defender可以在IE下载Gadget时,会自动扫描Gadget包中是否存在恶意代码。这种操作可以有效的保护用户,因为它是在Gadget运行前,甚至安装前就已经进行了。
Internet Explorer 7 保护模式
在Windows Vista中的Internet Explorer 7有一个新的安全特性,即保护模式。保护模式可以有效的阻止不被信任的站点中的恶意软件的侵扰。但保护模式对于Gadget无效,因为Gadget是运行在本地计算机上,并且与本地文件以及API相互交互。
完全信任
Gadget是迷你型的应用程序。虽然每一个单独的Gadget只有单一需求,比如读取文件或者远程机器上的信息,或者仅仅是显示一个按钮,或者其它功能等等。但是各个单独的需求汇集起来,就成为一个巨大的集合。为了更好的集成,所以我们给每一个单独的Gadget都设置为了完全信任模式,即第一次通过Windows Sidebar添加新Gadget对话框,并且信任后,以后执行时不再提示任何对话框。
附加的安全信息
如果您的客户在一个受组策略控制的环境下使用Gadget,可以限制Gadget的使用,以避免以上所提及的境况。Sidebar支持一种称之为共享Gadget文件夹的模式,这个文件夹可以在Program Files文件夹中找到。你可以将Gadget存放在此文件夹下,从而让本机上所有用户均可使用一份代码。你可以设置一个策略阻止用户再安装新的Gadget到他们自己的独享文件夹中。这个策略选项也可以阻止使用任何非共享Gadgets文件夹下的Gadget,而且只能通过某Administrator来更改此项策略。
Windows Sidebar共有以下的组策略选项以供定制:
- 关闭Windows Sidebar
- 禁止解压缩或者安装未签名的Gadget
- 关闭用户安装的Windows Sidebar Gadgets
- 覆盖“获取更多在线上小工具”链接
上个月,我宣布了Atlas的新官方名称以及讨论了这个完全支持的,基于ASP.NET 2.0 和 Visual Studio 2005 之上的1.0 版本的免费产品的发布计划。
今天,我非常高兴地宣布推出微软ASP.NET AJAX 1.0 版本的第一个Beta 。你现在可以在http://ajax.asp.net网站上下载这个版本。在该网站上,有以下三个下载选项:
1) The ASP.NET AJAX 1.0 版 “核心”下载。这个下载包括了为微软产品支持(Microsoft Product Support)完全支持的所有特性,即拥有标准的10年微软支持许可(一天24小时,一周7天,一年365天)。该下载包括了核心AJAX类型系统,网络协议层(networking stack),组件模型,扩展件(extender)基类,以及与ASP.NET集成的服务器端功能(包括广受欢迎ScriptManager,UpdatePanel,和 Timer控件)。
2) ASP.NET AJAX “增值”CTP下载。这个下载包括了以前各个Atlas CTP版本包含的,但并不在完全支持的“核心”1.0 版本内的额外的高级特性。在我们进一步完善这些特性,融合更多的反馈的同时,这些特性将继续得到社区支持。随着时间的推移,随着我们对这个增值包里的特性做进一步确认后,我们会陆续把特性移到“核心”下载版本里去。
3) ASP.NET AJAX 控件工具包。这个项目包含了基于ASP.NET AJAX 1.0 版“核心”下载版本的28个非常酷的免费AJAX控件。这个项目是协作性的共享源码,是由微软和非微软开发人员共同开发的,你今天就可以去CodePlex加入开发社区或下载代码。
Beta版本里做的一些变动
在这个Beta版本里,开发组做了不少变动。几个比较大的变动如下:
性能和下载文件大小的优化
以前的ASP.NET AJAX CTP版本依赖于浏览器下载一个包含所有特性的大JavaScript文件到浏览器上。对这个Beta版本,我们花了很多时间把特性抽取成多个文件,(这样,除非你要使用某些特性,否则你不需要下载它们),对整个库的下载大小做了优化。 ASP.NET AJAX “核心”下载现在只包括2个支持它的所有特性的JavaScript库:
a) MicrosoftAjax.js.gz脚本文件,包含了核心的JavaScript类型系统(type system),组件/控件模型,JSON网络协议和持久层(networking/serialization stack),应用服务特性(用户信息+认证),目前其大小为14.8k。
b) MicrosoftAjaxWebForms.js.gz脚本文件,添加了对使用UpdatePanel情形和页面局部更新的支持,其大小为6.4k。
在访问一个网站时,这些文件只被浏览器下载一次,然后它们就会被缓存在客户端,在访问该站其他的页面以及以后返回来再访问该网站时,这些文件就会被重用。这些新的文件大小可以确保在你第一次访问一个网站时给你一个既爽又快的体验。
除了优化JavaScript脚本库的初始下载文件大小外,我们也花了时间优化客户端JavaScript回调到服务器的网络传输数据的大小(network traffic size)。在默认情形下,象UpdatePanel和UpdateProgress这样的控件,以及控件工具包里的控件不再 发送 xml-script ,而是发送1-2行的JavaScript脚本,有助于极大地减小线上网络传输数据的大小。
在核心类型系统里,我们也从使用基于JavaScript closure的类转而使用基于prototype定义的类,因为我们发现对大多数常见的应用情形来说,这会减小内存的使用。
Safari 浏览器支持
以前的ASP.NET AJAX CTP 版本对Safari的支持不太好,譬如,UpdatePanel根本不工作。在这个Beta版本里,我们把Safari加入了完全测试过,完全支持的浏览器行列中。我们正在努力添加对Opera的支持,虽然在这个版本里,我们还没有准备宣称对它的支持,请静候更新消息。
显著改进的调试支持
随便哪个花过大量时间调试的人都可以作证,调试JavaScript经常不太好玩。我们在这个Beta版里做了2个重大的变动,有望极大地改进调试微软AJAX库的体验:
1) 把我们的JavaScript类定义从基于closure的模型转到了基于prototype的模型,你现在可以使用现有的Visual Studio 2005 脚本调试器(或者现有的其他JavaScript脚本调试器)查看和单步调试JavaScript 对象。以前Closure的方法掩藏了很多可以查看的信息。
2) 我们花费很多时间建立了一个自动的 JavaScript 生成环境(automated JavaScript build environmen),它允许我们为所有的JavaScript文件生成2个版本:一个优化了性能和下载大小的发布版本(retail version),和一个内含完整监测代码的调试版本(debug version),后者将有助于你在开发过程中找到代码中的问题。脚本文件的调试版本中的每个函数现在包含了对参数的验证编码,会在运行前核实传给函数的参数的正确性,假如参数有问题,就会报告出错并且提供运行栈(stack trace)信息。这有助于尽早轻松定位你的 JavaScript 编码的错误所在,有望极大地改进JavaScript调试。
注意事项:在默认情形下,究竟是使用AJAX 脚本库的发布版本还是调试版本是由你的web.config文件中的<compilation debug=”true|false” />设置来决定的。因为这客户端的参数验证编码会显著增加客户端脚本库的大小,而且对性能有极大影响,在部署你的应用前,确认你设置了debug=”false”。想了解为什么在部署ASP.NET 应用时,你应该始终设置debug=”false”的原因。
另一个注意事项:我们的计划是,让Visual Studio的下一个版本使用与运行时我们在调试脚本中使用的同样的参数验证元数据,在IDE里驱动IntelliSense和对JavaScript的句法检查。你可以把这元数据添加到你的代码中以改进验证,错误检查,以及最终也能给你自己的JavaScript 库提供IntelliSense功能。
UpdatePanel的改进
在这个Beta版本中,为融入客户的反馈,我们对 UpdatePanel 控件做了显著的改动。除了添加对 Safari 浏览器的支持外,这个Beta版本中的UpdatePanel 控件现在对以下几个方面提供支持:
a) 客户端脚本事件钩子(event hook),让你编写客户端 JavaScript 更轻松地参与脚本回调。
b) 能够让UpdatePanel中的控件触发页面局部更新的postback以及普通的postback ,这样你可以根据应用场景来做选择。你也可以禁止 UpdatePanel 中的子控件触发任何postback。
c) 能够在UpdatePanel控件中使用ASP.NET 验证和向导(Wizard)控件。以前的版本中有些bug防碍了这些控件的使用。
d) 能够动态生成和添加UpdatePanel 控件到页面中,而不用静态定义它们。这对控件开发人员尤其有用,因为他们现在能够在他们的复合控件里生成和使用UpdatePanel控件了。
e) 能够在一个页面里拥有多个 UpdateProgress 和动画效果控件,这些控件可以根据当前正在进行回调的那个UpdatePanel 有条件地运行。
f) 能够用声明的方式指定一个UpdateProgress控件应该等待多久才显示。这允许你对快速的UpdatePanel回调免于显示进度状况。
g) 在使用UpdatePanel情形下,对屏幕阅读器和其他accessibility工具的支持,以更好地实现Section 508标准。
Beta版重要注意事项:该Beta版中的UpdateProgress控件目前发布在“增值”下载中,所以你要用它的话,需要将其添加到你网站去。在下一个Beta版更新中,它将会被移到“核心”下载中,成为完全支持的应用情形。
客户端脚本库的许多改进
我们融合了客户的许多反馈,清理,简化,和改进了许多客户端JavaScript脚本库API。除了从closure模型转成prototype模型外,我们做了许多其他的API清理性变动,包括:
a) 简化了的JavaScript事件模型。现在,在客户端定义和attach事件更加容易。同时,对象事件也是按需才生成,以减少启动时间和所需内存(working set)的大小。
b) 简化了的组件,行为,和控件类型。现在,不用先生成相应对象,就可以调用有关的API,添加了按需(on-demand) semantics 以提高性能。
c) 改进了的客户端网络层。默认的回调函数和方法名semantics 提供了更加容易的方式以进行常见的异步回调。
d) 成员和用户信息(Profile) APIs。现在,在客户端JavaScript脚本中与成员和用户信息API交互的APIs更简单。
与其他AJAX库更好的兼容性
使用JavaScript的一个挑战是,不同的客户端 JavaScript 库间的冲突非常丑陋。以前的ASP.NET AJAX CTP版本中定义了一个名叫 $( ) 的辅助性函数,与其他常用的JavaScript 库(包括Prototype 和Scriptaculus)有冲突。
在这个Beta版本中,我们把我们的 $() 函数重新命名为 $get( ) ,同时还做了另外一些命名上的变动来允许多个独立的AJAX库在同一个页面上和平共处。
源码修改许可
我们收到的一个常见的请求是,开发人员要求能对微软AJAX 核心JavaScript库的源码做改动,譬如添加一个小的功能,微调一个实现,或者做个战术性的bug fix等。
我们将提供一个许可,明确地允许客户对这些库做改动,这个Beta中的ScriptManager API 现在允许你对内置的JavaScript库提供另外的实现或使用改动过的版本。除了允许你改动库代码为你所用外,这个许可也授予你再发布(redistribution)的权利,这样你可以把它们与你自己的组件和扩展一起发布。但对你再发布你自己的版本的一个要求是,你需要改变其中的命名空间以防冲突。
我们认为,完全的企业级支持(十年的支持服务)和修改代码再发布的权利之组合,真是强劲无比的offering,将提供给开发人员成堆的灵活性,无论他们项目的类型,大小和目标用户是什么。
下步计划
你也许从上面的段落里注意到了,这个Beta版有许多新的特性和变动。你需要对现有的ASP.NET AJAX编码做更新来反映这些变化。
如果你一直在用服务器端的 ASP.NET AJAX 特性,那么你会发现这些更新是比较直截了当的。这些更新主要包括,把控件的前缀从 <atlas:> 重新命名为 <asp:> ,改变UpdatePanel 控件的触发句法( trigger syntax),对控件工具包里的扩展件(extender)控件的声明方式做些小的句法变动。 如果你创建了你自己的JavaScript类型的话,或者你与组件模型直接交互的话,那么你需要做比较大的改动。在更新样本例子时,我们发现JavaScript的变动本身并不很复杂,但让人感觉沮丧的是,JavaScript无类型的灵活性阻碍了工具的编译检查,强迫你迭代地更新编码,反复寻找和改正每个变动,这有点枯燥和恼人。为帮你从CTP版移植到这个Beta版,ASP.NET AJAX开发组发布了一篇详细的文档,其中列出了所有的变动,还包括了编码例子示范常见模式和API用例的之前和之后版本。
ASP.NET AJAX 开发组也将在以后的几周内对论坛进行紧密的监视,帮助大家解决移植问题以及发现的任何问题。如果你遇上任何问题,发现了任何bug,或者需要任何帮助的话,请在论坛里发贴求助。
我们真的期待有很多人使用这个Beta 版本和希望得到更多的反馈。我们相信,与目前在ASP.NET AJAX v1.0 核心下载里的所有特性相对应的API的定义应该非常接近最后版本了,我们计划在今年剩下的时间里,不停地接受反馈和bug报告,稳定和锁定版本的特性。我们计划在几个星期后发布一个beta 更新版,融入客户的反馈,之后就发布一个RC版,然后在大家感觉一切就绪时就正式发布完全支持的1.0版本。
Master Page:母版页,用来定义页面的主要结构、显示样式。
Content Type:内容类型,SharePoint Server中用内容类型来定义页面的类型,比如“新闻页面”、“纯文字内容页面”等。通过定义一组Column,它决定了在一个页面上可以显示哪些信息。
Page Layouts:页面布局,定义页面如何将信息显示出来。每个Page Layouts都使用一个Master Page,同时与一个Content Type关联,这样,每个Page Layouts就可以定义出如何在页面上将Content Type中定义的信息显示出来,即Content Type中每个Column中的信息显示在页面上的哪个地方。通常,我们会在Page Layouts上面放一些Field Control,每个Field Control对应到一个Column。
Page:页面,其实SharePoint Server里面的Page不是一个真正的页面文件。当我们创建新的Page时,会选择创建哪种Content Type的Page,然后,SharePoint会让我们从某个Page Layouts(当然这里可供选择的Page Layouts必需是和这个Content Type相关联的)中选择一个,最后,通过输入Content Type中定义的Column的值,一个Page就创建完成了。每个Page都只是一个保存在Pages列表里面的一个ListItem。
页面输出的步骤:
1、用户从客户端请求访问一个页面。
2、SharePoint从Pages列表中找到这个请求页面对应的ListItem。
3、根据ListItem的对应栏的值,SharePoint找到它相关联的Page Layouts,把Page Layouts上的信息取出来。
4、根据Page Layouts的定义,把其使用的Master Page的信息取出来。
5、运行页面。
6、页面上的Field Control会从页面对应的ListItem的相应栏里面把值取出来,显示在Field Control里面。
[Original Post: Yahoo -?Microsoft: Excuses on iPod virus not credible]
San Francisco (InfoWorld) - Security and quality assurance experts reacted negatively to Apple Computer's efforts Tuesday to blame manufacturing problems that resulted in iPod MP3 players shipping with a virus that affects Microsoft's Windows operating system.
That statement drew criticism from security experts, including Jonathan Poon, the man in charge of scanning Microsoft products for viruses before they ship.
"It's not a matter of which platform the virus originated [on]. The fact that it's found on the portable player means that there's an issue with how the quality checks, specifically the content check, was done," Poon wrote in a blog entry.
James "Randy" Abrams, who held Poon's job for more than a decade at Microsoft and is now director of technical education at ESET, agreed.
"The Apple iPod incident was not about Microsoft having a hardy operating system, it was all about security and process," Abrams told InfoWorld in an e-mail message.
Viruses on Microsoft's network weren't unusual when Abrams was testing that company's products before shipping them, he said.
"I released software in an environment surrounded by Windows machines. Many machines on the corporate network were infected. We never introduced a virus into the software in the release or manufacturing processes because we had a professional understanding of what it took to release what we were supposed to," he said.
"That Apple would blame Microsoft demonstrates a lack of understanding of remedial security and manufacturing processes. Virus was only a symptom of the problem. Apple didn't know what they were shipping," Abrams said.
Apple did not respond to phone and e-mail requests for comment before this story filed.
The news about the infected iPods was the second such story in recent days. On Monday, McDonald's admitted that 10,000 MP3 players that were given away in a promotion in Japan also contained a worm, identified as WORM-QQPASS.ADH.
Both Poon and Abrams said that Apple's response to the infected iPods fell short of McDonald's, even though the burger giant has precious little experience in the consumer electronics space.
"The difference in how McDonald's and Apple handled similar incidents paints a stark difference between management integrity and customer service focus," Abrams wrote.
"Both cases were flawed manufacturing processes. Mistakes can happen and smart companies accept responsibility, make things right with the customer, and fix the problems. Lesser companies play the blame game," he wrote.
McDonald's fix: a single link to Trend Micro's "Housecall" online virus scanning service and an open offer to replace infected players for free also won praise over Apple's response: a bunch of links to free antivirus software trials, including Microsoft's OneCare program, Poon wrote.
"Steve, if you need someone to advise on how to improve your quality checks, feel free to contact me," Poon said, referring to Apple CEO Steve Jobs.
Software companies have long known about the potential to introduce viruses and other malicious code during the manufacturing process, and have developed procedures to catch such infections.
Two such episodes in a week might indicate that malicious hackers have figured out that consumer device makers are less vigilant in their oversight, said Dennis Szerszen, vice president of marketing and corporate strategy at SecureWave, an end point security software vendor.
Apple may have had more lax oversight around the iPod because it wasn't software and wasn't, in itself, targeted by malicious code, he said.
"There may have been less rigor because they weren't cutting and shipping an OS," he said.
Given that, Apple is lucky that it was a virus that shipped on the iPods rather than pornography, pirated software, or some kind of religious or political propaganda that would have been even more damaging to Apple's name, Abrams said.
iPods and other consumer devices are increasingly finding their way onto enterprise networks, and are an increasingly common vector for attacks, he said.
""The end point is the final frontier in enterprise security, because it's where you and I bring our recreational attitudes and personal choices for how to work to bear," he said.
Companies should set up stringent policies about whether and how to use consumer electronics devices at work, but also set up systems to monitor their use and prevent malicious attacks or infections that might be carried by iPods, PDAs, and other consumer devices, Szerszen said.
[来源:Saveen Reddy] .NET 框架类库本身没有提供工具分析HTML,以前常用的做法是用正则表达式,或者浏览器控件,或者MSHTML组件,甚至SgmlReader。SgmlReader可以将HTML转化成XML,然后你就可以使用System.Xml命名空间下的类对文件进行查询。
CodePlex上有一个Html Agility Pack项目,是原生的.NET项目,不依赖MSHTML或者ActiveX/COM 对象。其中的HtmlDocument可以加载任何HTML文件(即使该文件是不well-formed的HTML),然后允许你使用类似于System.Xml的对象模型对文件进行查询。
譬如,
HtmlDocument doc = new HtmlDocument();
doc.Load("somehtml.html");
Console.WriteLine(doc.DocumentNode.InnerHtml);
foreach ( HtmlNode node in doc.DocumentNode.SelectNodes("//a"))
{
string url = node.GetAttributeValue("href", "");
Console.WriteLine(url);
}
【原文地址】Visual Studio for Database Professionals and other Cool Data Management Tools for .NET
【原文发表日期】 Wednesday, October 18, 2006 7:40 AM
今天早先时候,我们发布了Visual Studio Team版的数据库专业人员版的第六个社区技术预览版(CTP)供免费下载。
Visual Studio 数据库专业人员版获得的好评如潮,其功能包括对数据库重构,数据库定义和数据的比较,数据库单元测试,以及自动的数据生成的支持。你可以在它的MSDN开发人员中心及其社区网页上了解更多的相关信息。你也可以在这里观看一个 Channel9 采访该产品开发组的录像。
我最近在 http://weblogs.asp.net 上看到了另外2个数据管理工具,看上去非常酷,值得花时间看一下:
MassDataHandler ── 一个免费的CodePlex项目,提供了一个可以为单元测试自动生成数据的工具库,可以和任何单元测试框架一起使用。
Data Dictionary Creator ── 一个免费的工具,可以帮助你管理SQL服务器数据库的文档,帮你把文档与数据定义的变动保持同步。
希望本文对你有所帮助,
Scott
从1999年开始,这是我第七次在北京参加微软公司的Tech ED。7年来,我的角色从程序员、系统管理员/网络管理员转变为评测工程师,因此,每次参加Tech ED,都能找到一些往日的感觉,却又感受到更多的变化的成分。
随着Tech ED的课程系列越来越多,我经常会遇到选课的难题,作为媒体参会者,我需要了解新技术和新产品以便报道,对评测工作来说,最有用的却是主流产品的深入应用和性能优化方面的课程,这时我只能选择后者,因为前者可以比较容易地通过讲义中的课程大纲来了解。至于遇到Windows平台、开发、系统结构、安全、Exchange等几个系列课程的撞车,也是家常便饭。
随着会议规模的不断扩大,Tech ED的举办地点也逐年变迁,先是从中国大饭店搬到了国际会议中心,今年又搬到了新落成的九华国际会展中心。这可能是目前北京最大的单体结构会展中心了。在一个建筑内,可以容纳数千人规模的展会和相关人员的住宿。
Tech ED的惯例是请一位微软的全球副总裁来做第一天上午的主题演讲,这次竟是Andy Lees,他是负责微软服务器和开发工具的副总裁,Tech ED正在他的管辖范围,但在我的印象中,他是第一次在北京的Tech ED上出现。
他的演讲内容很丰富,主要概括了微软最近在企业级计算市场、开发工具方面的新进展和近期的产品规划。不过最精彩的还是两个展示,一个是Windows Vista,华丽的视觉效果博得了满堂掌声,另一个是由北工大的在校学生使用微软的.NET开发工具实现的fego网络虚拟社区。无论是创意、界面和功能实现都值得称道。自Windows XP开始,微软把自己一向擅长的产品易用性包装和发展成为“用户体验”,从那之后的桌面产品和开发工具都向这个理念靠拢,到了Windows Vista时代,这种理念显然又将发展到一个新的高度。不过我也担心,以后基于Vista平台进行人机交互时系统的负载就像是现在我们在玩3D游戏,这对现有的多数PC平台的配置都是一个挑战。因此,Vista成功的时候,也就是大规模PC升级的日子了。同时,我相信虽然Windows Vista和未来的Windows longhorn Server(微软暂定名)的主要版本号都是6,但主要组件的差异将会前所未有地加大,至少Avalon之类的UI技术几乎不可能在服务器版本上出现。
主题演讲10:45开始,结束时已经是12:20,午饭时近2000人一起进餐的场面很壮观,让我想起了2004美国Tech ED时圣地亚哥展览中心的万人大食堂。虽然论规模,中国的Tech ED还是比不上美国,但这次参会者数已经超过了3200人,如果再加上广州和上海的参会者已经超过5000人。
这次Tech ED共安排了9个分会场,也就是说有9个系列的课程。吃饭的时候我查了一下课程表,在下午的4节课中,前两节我选择了Windows系列的“Windows Server 2003 R2概览”以及“微软统一身份管理和访问控制(IAM)解决方案和产品路线图”,后两节我选择了系统结构系列的“协调业务与IT业务构架设计”和IT系列的“微软IT业务”。虽然对于其他的关于IE 7.0新特性、Xbox360开发、消息队列、Exchange、安全方面的课程也有兴趣,但只能回去再看网上的WebCast。
前两节课中,我了解到Windows Server 2003 R2的一些情况,这是继SP1之后的又一次升级,它更新了很多驱动程序,修复了很多问题,但它之所以没有被称做“Windows Server 2003 SP2”是因为它引入了不少新的特性,而且将作为一个新的Windows产品来发布。新的特性包括Active Directory Federal Service(ADFS)以及其他管理和存储方面的工具。ADFS使得统一身份管理和访问控制更加容易实现,对于开发者和IT管理人员来说,这降低了异构环境中的应用程序设计和业务系统迁移的复杂度,对于最终用户来说,通过单一登录即可确认身份,在使用网络连接、访问文件/打印服务和使用业务系统(无论是传统的C/S应用还是Web Service应用)时的角色和权限都得到完整的控制和规划。后两节课使我对微软处理IT系统与业务关系的方式以及新的事件驱动的商业模型有了进一步的了解。
9月24日,三堂课
第二天,我选择的第一堂课是“简单之美——实战ASP.NET 2.0”,与前面版本相比,ASP.NET 2.0在编程方面提供了更高的自动化程度,一些新的控件进一步简化了编程步骤,同时提供了更多的新功能,此外在安全和配置方面也有了提高。不过,给我留下深刻印象的是数据源方面竟然支持基于对象的存储,从编程的角度看,这提供了对象序列化的支持,对于应用的迁移、备份以及提高业务连续性方面显然会有帮助。
第二堂课选的是“监视Microsoft平台和应用程序”,我来到课堂的时候,上一节课的讨论还没有结束,上面在答疑的讲师是我认识的栾跃。
说到栾跃,正好可以提一下Tech ED的讲师构成,总的来说分为两类,一类是微软公司的专家,另一类来自微软的合作伙伴,主要是来自各个微软认证培训中心的讲师。前者的优势往往在于对于产品技术了解的深度,对用户需求的深刻把握和大量的实战经验,而后者的优势主要在于讲课的技巧和逻辑。在来自微软的专家讲师里,有些是顾问/咨询/支持人员,这类讲师与客户接触较多、拥有大量案例经验,授课相对比较精彩,还有些是产品组开发组的成员,他们对于产品的设计理念、规划方面的知识经验是别人很难企及的。当然,还有一类是业界泰斗,例如Tech ED 2004的C++大师Lippman。来自认证培训中心的专业讲师都是行内的佼佼者,通常拥有微软认证的培训师(MCT)资格,其中也不乏拥有丰富案例经验的人。栾跃是来自微软的专家讲师,他的软件开发项目管理课程是几年来Tech ED的重头课,一直深受欢迎,这次他除了第一天的软件开发项目管理外,今天又开了一节SOA方面的课程。
第二堂课的内容是关于MOM的,MOM是微软近两年发展起来产品,用于服务器运行监控和维护操作,是微软实现DSI(动态系统倡议)战略的重要产品。听了大约30分钟后,我觉得已经基本了解了自己需要的内容,就走出去准备再听听有关Windows Vista的课程。在路过动手实验室的时候,发现有个实验的内容是“Exchange Server性能检测”,已经开始了半个小时,不过还有实验机,遂决定放弃Vista课程,做一节实验。Exchange Server是微软最为倚重的服务器产品,也是我比较熟悉的产品。实验的内容主要是通过系统的“性能”MMC来查看与Exchange相关的性能指标,了解Exchange的健康状况,实验步骤很多,要到12点才结束,但我选的下一节课11:30就要开始了,我只好抓紧在半个小时内把实验做完,中间还经历了两次虚拟机崩溃。不过,在实验过程中,我发现了一个有意思的现象,在大容量(1280MB)物理内存的环境下,相同压力下的磁盘读写次数要高于低容量(256MB)的环境,指导教师认为是Windows内存管理的机制造成的,我准备回去后再深入探讨。
第三堂课是“Exchange Server邮件系统容量规划”,与刚才动手实验室的内容相关性很大,组织者如果能把这两个内容分开安排效果显然会更好。这堂课的讲师是叶晓彬,来自微软的咨询顾问部门,她讲的内容与我们的服务器评测工作非常相近,只不过角度不同,我们要考察服务器方方面面的性能,而她的出发点是单一的应用,也就是Exchange。但是微软在Exchange性能测试和容量规划方面的方法论和工具都值得我们借鉴,对于IOUS指标的强调也使我获益匪浅。
随后就到了午饭时间,由于在上午的课程中比较投入,我打算下午第一节选个相对轻松的课程,最后选定了“无线网络安全对策”。这堂课使我对微软WLAN安全功能实现有了新的了解。不过在我看来,微软的WPA整体解决方案与基于FreeBSD/Linux和FreeRadius的方案相比,在实现复杂性上没有明显的优势,至少没有把微软善于整合的特长发挥出来,当然,如果考虑到AD的因素,多数企业用户会使用微软的方案。
随后两节课我选择了WHQL方面的课程,虽然WHQL测试和我们的评测工作侧重点不同,但是微软测试的工程方法是值得我们借鉴和参考的。
下午5点左右听完了第三节课后,我决定放弃最后一节,去看看合作伙伴的展区。这次Tech ED现场合作伙伴的数量也是历年来最多的,一层是微软、AMD、Intel的展台,人气一直很旺,显示了平台系统和处理器提供商在IT生态系统中的基础地位。二层主要是独立软件开发商和方案提供商,包括Oracle、EMC、Brocade、HP和多普达,在微软的活动中看到Oracle的展台是不多见的,虽然两者的产品有直接竞争关系,但微软在提供越来越好的企业级系统平台是不争的事实,也许正是这一点促成了两家的合作。
晚饭时微软请来了乐队,主唱的嗓音酷似张靓颖。
9月25日,感受虚拟化技术
和前两天比起来,第三天的课程在内容上毫不逊色。在选择第一节课时就让我犯难。在虚拟化技术、Indigo和ASP.NET性能优化中,我最终选择了和工作密切相关的ASP.NET课程。事实上,在我们的服务器测试工作中,我发现.NET framework中间层的加入对于性能提高有了不小的影响,进一步了解ASP.NET有助于我们优化测试脚本。
第二节课我选择了“Microsoft Virtual Server以及虚拟化技术的未来”,这也是我在Tech ED中印象最深的一堂课。讲师傅雄俭来自微软的虚拟化产品开发组,作为世界领先的IT公司,微软的技术能人众多,但大多是某一个方面的深度专家,而傅雄俭拥有在微软少见的体系结构把握能力,对授课的好处是能够把内容真正讲透,并使授课内容在逻辑和体系上趋于完备。因此,听他的课有一种很“痛快”的感觉。也使我在短时间内对微软的虚拟化技术有了一个相对全面的了解。其实,在这次Tech ED中,虚拟化技术已经随处可见,多数讲师会用Virtual PC来搭建演示环境,当然还很少有人把微软的虚拟化产品用于生产环境,但从微软的产品规划来看,近期将发布的Virtual Server 2005 R2将支持Linux,并具有更好的性能,很可能会成为大规模部署在生产环境中的第一个微软虚拟化产品。而2006年,在Intel VT和AMD Pacifica等针对虚拟化技术的CPU支持功能实现之后,他们的Hypervisor产品就能跟上竞争对手VMware的步伐,甚至开始在某些方面领先。我还了解到,在下一代Windows Server产品中,虚拟化技术将扮演重要的角色。前些时候我测试了IBM的OpenPower产品,切身体会到了虚拟化技术为企业级用户带来的好处,事实上,除了计算密集型或I/O密集型业务之外,虚拟化技术可以用在企业计算的各个方面,使企业应用的整合、分发、迁移、备份、升级以及业务间隔离等工作得到极大的简化。当然,由于虚拟化技术引入了中间的资源管理和调度层次,我们无法期望在Guest OS上运行应用的性能跟在物理机上一样好,但随着技术的不断发展,性能越来越不是问题了,这对虚拟化技术来说显然是件好事。
第三堂课我听的是Jasper和Johansson的“安全神话”(the security myth)。他们来自微软的安全规划部门。在所有Tech ED的讲师中,两个短打扮的“老外”显得很突出,在课前,很多参会者走过来请他们一起合个影。课程讲得是一些看似安全实则无用的做法,例如账户锁定、信息隐藏等。课堂气氛热烈,互动性很强,但内容并没有使我感到意外,事实上,就在前些日子,slashdot.org上面也有类似的深入讨论。这种课程挑战了很多传统的观念,但是没有提出系统的答案,也许真正的答案就在那本他们合著的书里吧。
因为是最后一天,所以下午只有两堂课,第一节课我选了“拒绝垃圾信息——企业用户如何阻挡SPAM和SPIM”,这门课和前面“Exchange Server 2003 SP2新特性”的课内容有些重复,但我由于课程冲突错过了前面一节,正好补一下。2004年早些时候,微软曾计划要发布一个专用于邮件过滤的Edge Service(实际上是一个带过滤功能的SMTP网关)产品,但后来改变了这个计划,而把Edge Service的功能整合进了Exchange Server 2003 SP2中,其中最主要的就是Seder ID。如今,微软公司的邮件系统和Hotmail都已经实施了Sender ID技术,但要这种技术真正发挥作用,可能还需要很长时间的推广。
最后一节课听的是“Visual Studio Tools 2005 for Office——快速打造Office商业应用的利器”,VST 2005 for Office的前身是VBA,与前面版本相比,它与Windows Form开发环境达到了无缝的整合。对于中小企业用户,基于Office开发应用是一种高效低成本的做法。
结束了3天的紧张课程之后,我不禁想起了很久以前做学生时候的辛苦。这时,会展中心的大门口竖起了“相聚Tech ED 2006”的大牌子,不少人在下面合影留念。
| --> |
李志宵作为微软(中国)有限公司首席技术执行官,在这次大会演讲中首次阐述了微软近期发布的“全员就绪(People-Ready)”理念。当然,一再推迟发布的Windows Vista也成为这次大会的焦点,“创新”是这次大会力求突出的主题。
李志宵在会上着重强调了软件的创新方向及软件在企业中应该发挥的作用,他表示:“当今,IT并不普遍被看作是推动企业成长的关键因素,微软坚信软件的不断创新对驱动企业成长至关重要。”
对于大家都比较关心的Vista的推广问题,微软表示,主要是与OEM厂商以及企业合作,其次是通过系统升级来完成。在Vista的发布时间问题上,微软也明确地表示,对于商业用户,会在11月底12月初发布,而最终用户将在2007年的1月就可以直接体验。













