SharePoint 2010中的客户端AJAX应用——ASP.NET AJAX模板

WCF Data Services是SharePoint 2010中一个极具吸引力的新特性。然而,因为它的强大,直接对其进行编程仍然会有点痛苦。幸运的是,一个新的相关技术 —— ASP.Net AJAX模板 – 可以完美的与WCF Data Service进行集成,并允许我们快速构建优雅的,可维护的和反应迅速的AJAX应用程序。 

在本文中,我将详细描述ASP.Net AJAX模板,并在Visual Studio 2010中一步一步的构建一个非常简单的应用程序页面。接着使用ASP.Net AJAX模板来显示SharePoint 2010中通过WCF Data Services发布的JSON格式的列表数据。 

什么不是模板? 

单纯从技术层面解释什么是ASP.Net AJAX模板可能并不容易。不妨先假设没有这项技术,看看传统方式是如何解决问题的。如果SharePoint传递给你一个JavaScript中的JSON对象的数组,现在的你会如何将其转换成HTML? 

最常见的答案似乎就是JQuery的.append()语句了。代码大致如下:

for  ( var  i  =   0 ; i  <  userStories.length; i ++ ) {
$(
" #userStories " ).append( " <div class='userStoryCard'> "   +
userStories[i].Title 
+   " </div> " );
}

这种类型的解决方案的问题,或者说任何没有使用模板引擎的解决方案,事实上都无法清楚的分离数据访问逻辑和界面展现。事实上,这种情形很像回到了经典的Active Server Pages风格,可维护性很差,代码一塌糊涂。随着我们不断的从SharePoint获取数据,整个代码会变得更加杂乱。 

模板的目标是使你不必编写上面那样的代码,使用模板后的代码应该像下面这样:: 

< div  class ="userStoryCard" > {{ Title }} </ div >

整洁,漂亮。理想状态下模板应提供这样一个的解决方案: 

  • 最大限度地减少管道(plumbing)代码 
  • 清晰的分离数据访问逻辑和界面展示 
  • 简化存回服务器端的数据 
  • 并且没有ViewState!  

ASP.Net AJAX模板的昨天,今天和明天 

如果你读过Scott Guthrie的博文jQuery templating engine  ,或者你曾非常不容易的看到过准确介绍jQuery模板的官方文档,你就会惊讶于为什么ASP.Net AJAX模板与其如此之符合,这也正是微软构建客户端AJAX应用的愿景。 
首先,在ASP.Net AJAX项目还是beta阶段时,模板就已经存在了。当ASP.Net AJAX 4.0从测试转到正式发布后,模板JavaScript文件被纳入到AJAX ControlTooklit CodePlex项目(语法稍作修改)。这就是为什么你会发现今天网上找到的大多数例子都稍微有些过时。
至于jQuery的 模板引擎,据Stephen Walther(ASP.Net MVC团队的项目经理)所说,他们“未来不会投入过多精力到[ASP.Net AJAX的模板]”,因为他们将会把重点放在jQuery模板引擎。那么我们何必学习一门不会有所发展的技术呢?原因之一是jQuery模板引擎仍非常年轻(撰写本文时还处于原型阶段),而ASP.Net AJAX模板已正式发布,可以直接用于生产环境。另一方面,其语法很接近,想必将来升级也不会成为一个大工程(理论上如此)。 

Visual Studio 2010和SharePoint 2010 

在进入模板学习前,让我们先来快速看一下如何在Visual Studio 2010中构建一个应用程序页面。这是我们将来编写代码的基础。当然你可以把所有代码都放在一个内容编辑器Web部件里,但是Visual Studio提供了更好的智能提示和调试的支持,因此我们选择在应用程序页中运行。

为了在Visual Studio 2010中建立一个简单的应用程序页面,先选择“新建项目”,然后导航到SharePoint 2010模板分类,选择“空白SharePoint项目”

ajaxcli01.PNG

点击确定后,Visual Studio会弹出SharePoint自定义向导:

ajaxcli02.PNG

该窗口要求你选择一个站点用于调试。当你按F5键(开始调试)时,Visual Studio 2010会进行wsp文件打包,然后将其部署到这里你填写的URL对应的站点上,同时附加上对应的w3wp进程,并打开一个浏览器显示该sharepoint站点。这样,你就立即拥有一个调试环境了。

如果你对这一过程印象不深刻,那么你可能没有做过多少WSS 3.0的开发——但请相信我,这个改进大大节省了我们的时间。尽管在本例中我们不会写任何服务器端代码,但仍旧可以体会到微软在SharePoint 2010上倾注了不少的心力。 

当Visual Studio完成项目初始化后,选择项目->添加新项,然后选择应用程序页。 

ajaxcli03.PNG

Visual Studio接下来会自动生成一个完全套用SharePoint母版页并包含内容控件的页面。

ContractedBlock.gif ExpandedBlockStart.gif 代码
<% @ Assembly Name = " $SharePoint.Project.AssemblyFullName$ "   %>
<% @ Import Namespace = " Microsoft.SharePoint.ApplicationPages "   %>
<% @ Register Tagprefix = " SharePoint "  Namespace = " Microsoft.SharePoint.WebControls "  Assembly = " Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Register Tagprefix = " Utilities "  Namespace = " Microsoft.SharePoint.Utilities "  Assembly = " Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Register Tagprefix = " asp "  Namespace = " System.Web.UI "  Assembly = " System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 "   %>
<% @ Import Namespace = " Microsoft.SharePoint "   %>
<% @ Assembly Name = " Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Page Language = " C# "  AutoEventWireup = " true "  CodeBehind = " UserStories.aspx.cs "  Inherits = " PreDemo.Layouts.PreDemo.UserStories "  DynamicMasterPageFile = " ~masterurl/default.master "   %>
< asp:Content  ID ="PageHead"  ContentPlaceHolderID ="PlaceHolderAdditionalPageHead"  runat ="server" >
</ asp:Content >
< asp:Content  ID ="Main"  ContentPlaceHolderID ="PlaceHolderMain"  runat ="server" >
Hello World!
</ asp:Content >
< asp:Content  ID ="PageTitle"  ContentPlaceHolderID ="PlaceHolderPageTitle"  runat ="server" >
应用程序页
</ asp:Content >
< asp:Content  ID ="PageTitleInTitleArea"  ContentPlaceHolderID ="PlaceHolderPageTitleInTitleArea"  runat ="server"   >
我的应用程序页
</ asp:Content >

(“Hello World!”是我写的)。现在如果你按F5键或者点击生成->部署解决方案,则Visual Studio会打包该应用程序页到一个wsp文件并将其部署到SharePoint。如果你导航到该应用程序页的话(例如本例中为http://contoso14/_layouts/PreDemo/UserStories.aspx)则会看到如下的显示:

ajaxcli04.PNG

很震撼吧!你真的应该如此。我们没有编写冗长的,重复的代码,或者容易出错的CAML,没有运行任何DOS(或PowerShell)脚本,没有手工部署到GAC,甚至没有注意到后台自动生成的Feature.xml文件,然而,我们已经部署完了。

安装ASP.Net AJAX模板

ASP.Net AJAX模板的安装比较棘手。为了得到它你需要先在CodePlex上下载最新推出的AJAX控件工具包源代码(本例中下载下来的是AjaxControlToolkit-9c860ac12ae9.zip)。并在Visual Studio(它的项目中包含了Visual Studio 2008和2010两个版本)中编译(编译时还需要安装Microsoft Ajax Minifier 2.0)然后将Javascript文件复制到SharePoint的layouts目录下。需要复制的目录有:

从 AjaxControlToolkit.Source\SampleWebSites\AjaxClientWebSite\Scripts; 复制到

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\ \14\TEMPLATE\LAYOUTS\Scripts

还有从 AjaxControlToolkit.Source\Client\MicrosoftAjax\Templates; 复制到

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\ \14\TEMPLATE\LAYOUTS\Scripts

或者采用更符合标准的做法,将其复制到Visual Studio项目的layouts目录中。

代码

Javascript文件都就位后,我们就可以编写最简单的模板页代码了:

<% @ Assembly Name = " $SharePoint.Project.AssemblyFullName$ "   %>
<% @ Import Namespace = " Microsoft.SharePoint.ApplicationPages "   %>
<% @ Register Tagprefix = " SharePoint "  Namespace = " Microsoft.SharePoint.WebControls "  Assembly = " Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Register Tagprefix = " Utilities "  Namespace = " Microsoft.SharePoint.Utilities "  Assembly = " Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Register Tagprefix = " asp "  Namespace = " System.Web.UI "  Assembly = " System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 "   %>
<% @ Import Namespace = " Microsoft.SharePoint "   %>
<% @ Assembly Name = " Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c "   %>
<% @ Page Language = " C# "  AutoEventWireup = " true "  CodeBehind = " UserStories.aspx.cs "  Inherits = " PreDemo.Layouts.PreDemo.UserStories "  DynamicMasterPageFile = " ~masterurl/default.master "   %>

< asp:Content  ID ="PageHead"  ContentPlaceHolderID ="PlaceHolderAdditionalPageHead"  runat ="server" >
< style  type ="text/css" >
.sys-template 
{
    display
: none ;
}
</ style >
< script  src ="/_layouts/Scripts/MicrosoftAjax/Start.js"  type ="text/javascript" ></ script >
< script  src = "/_layouts/Scripts/MicrosoftAjax/MicrosoftAjax.js"  type ="text/javascript" ></ script >
< script  type ="text/javascript" >
Sys.require([
Sys.components.dataView,
Sys.components.openDataServiceProxy,
Sys.scripts.jQuery
]);
Sys.onReady(
function  () {
    
var  dataSource  =  Sys.create.openDataServiceProxy( ' /_vti_bin/ListData.svc ' );


    Sys.query(
" #userStoriesList " ).dataView({
        dataProvider: dataSource,
        fetchOperation: 
" UserStories " ,
        feachParameters: { orderby: 
' 标题 '  },
        autoFetch: 
" true "
    });

});
</ script >
</ asp:Content >
< asp:Content  ID ="Main"  ContentPlaceHolderID ="PlaceHolderMain"  runat ="server" >
Hello World!
< ul  id ="userStoriesList"  class ="sys-template" >
< li > {{ 标题 }} </ li >
</ ul >
</ asp:Content >
< asp:Content  ID ="PageTitle"  ContentPlaceHolderID ="PlaceHolderPageTitle"  runat ="server" >
应用程序页
</ asp:Content >
< asp:Content  ID ="PageTitleInTitleArea"  ContentPlaceHolderID ="PlaceHolderPageTitleInTitleArea"  runat ="server"   >
我的应用程序页
</ asp:Content >

其中的UserStories是我的一个任务列表。我事先填充了一些示例数据。

跳过JavaScript部分,我们先来看Main content一节中名为userStoriesList的<ul>无序列表。 其中的<li>元素包围着一个有趣的符号:{{ 标题 }}。这样就声明了一个绑定到SharePoint中ListItem的标题字段。我们也可以改成任何其他的列,如“优先级”,或者在其中添加JavaScript,如{{ String.format("{0:yyyy-M-dd}", 修改时间) }}。

注意PageHead的脚本引用。引用MicrosoftAjax.js使得我们可以使用ASP.Net AJAX的核心功能。Start.js使得我们可以使用Sys.require功能,以便导入其他具有依赖关系的Javascript。

至此,我们还没有导入足够的JavaScript以提供我们需要的模板功能。这部分工作由Sys.require来完成。声明了1.DataView对象,用于完成主要的模板工作;2.openDataServiceProxy,知道如何与SharePoint的ADO.Net Data Service进行通讯;3. jQuery。如果你用Firebug看的话就会发现Sys.require加载了哪些额外的.js文件,就像MicrosoftAjaxTemplates.js。而且是按照正确的顺序加载到页面上的。这种方式保证了页面不会放上很多不需要的Javascript。 

真正的奇迹发生在Sys.onReady里,其功能是在DOM加载完成后执行一次。首先它实例化了一个openDataServiceProxy对象,负责与一个oData端点进行通讯,在我们的例子中是一个ADO.Net Data Services。

它做的第二件事情是实例化一个DataView对象,并将其关联到userStoriesList元素。fetchOperation参数告诉它从哪个列表获取ListItems(本例中为UserStories列表)。fetchParameters参数告诉它如何对数据进行排序,筛选或分页。

DataView实例化后(由于autoFetch被设为true) 会通过其dataProvider检索JSON数据,并为每个返回的行重复所关联的DOM元素的innerHTML,而且以实际的数据代替绑定语法。看起来似乎很简单,但在将来的博文中你会看到它很快会变得很复杂。

最后一个要注意的是sys-template类。这是一个在ASP.Net AJAX中预定义的CSS类,当完成渲染工作后,由ASP.Net AJAX将其设置为display:block。因此,我们需要为sys-template创建一个CSS类并设为display:none,这样在页面加载过程中最终用户就看不到你的模板代码了。

现在,如果你点击生成->部署解决方案,就会看到如下的显示: 

ajaxcli05.PNG

总结

当然,可能如果用服务器端代码编写这个功能的话实现起来更容易。这个话题先搁在这儿,我们的解决方案还有很多潜力可挖。例如,从哪个层面上与jQuery结合,可以使界面更美观?如何将数据写回到上下文服务器端?如何实现主-子关系?我们将在随后的博文中一起来探讨这些问题。

 

参考资料

Client Side AJAX Applications in SharePoint 2010-Part3:ASP.Net AJAX Templating 101 

ASP.NET AJAX: Client Postbacks cause a Sys.ArgumentTypeException 

 

转载于:https://www.cnblogs.com/Sunmoonfire/archive/2010/07/22/1781936.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值