SharePoint 客户端对象模型 (一) ECMA Script |
||||||||||||||
本文标签:SharePoint,客户端 所谓的客户端对象模型就是调用了背后的WCF服务来提供数据,为了减轻数据的访问量数据包使用JSON,我们还可以看到对象模型的设计也加入了诸多对于减轻数据访问量的考量 。技术上没有什么新意,你要愿意,在SharePoint2007里面也可以实现类似的功能,当然在使用上方便了我们不少
本文讲阐述如何使用.NET托管代码来访问SharePoint对象模型 。 ECMAScript Client OM需要注意的几个点
我们看看SharePoint OM和客户端OM的一个简单的匹配关系:
看看最后会呈现的效果,下图是初步计划的功能,主要设计列表的创建、查询以及管理,另外也涉及上传文件的Case,后续里如果有重要的也会逐步加进来 。
里面的链接会调用UI方面的Javascript接口创建SharePoint2010风格的弹出窗口,弹出窗口的后台页面位于SitePage文档库内,请注意这个仅仅适用于打开的页面是WebPart page,如果不是打开的时候会报错误:“The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist” 。 (注意,此Page在之后都不会被用到,留在这里仅为了解释Ribbon用) 创建列表: 首先,通过Designer,加入以下两个Script链接: <SharePoint:ScriptLink Name="SP.js" runat="server" OnDemand="true" Localizable="false" /> ECMAScriptOM和.NET Managed ClientOM(随后会讲到)异曲同工,但也有几点需要注意的:
代码非常的简单易懂,里面有个好玩的东西SP.UI.Notify.addNotification,通过这个类可以在调用的画面里显示提示消息,非常的SharePoint 。
演示结果如下: 在文本框里输入列表名字后,点击"Create List”按钮,生成列表后会在右上角提示“List test1 created”,本例中使用annoucement做为列表类型 。
源代码如下: 复制代码 代码如下: <script type="text/javascript"> var messageId; function createList(listName){ var clientContext = new SP.ClientContext(); var oWebSite = clientContext.get_web(); var listCreationInfo = new SP.ListCreationInformation(); listCreationInfo.set_title(listName); listCreationInfo.set_templateType(SP.ListTemplateType.announcements); listCreationInfo.set_quickLaunchOption(SP.QuickLaunchOptions.on); var oList = oWebSite.get_lists().add(listCreationInfo); clientContext.load(oList); clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed)); } function onQuerySucceeded() { //Remove the creating event notification if(messageId != null) { SP.UI.Notify.removeNotification(messageId); } //Add created notification as non sticky messageId = SP.UI.Notify.addNotification("List <b>" + oList.get_title() + "</b> created...", false, "", null); } function onQueryFailed(sender, args) { //Remove the creating event notification if(messageId != null) { SP.UI.Notify.removeNotification(messageId); } //Shown in case of error on the JS OM call messageId = SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null); } </script> 获取所有列表: 同样,先看一下效果,点击“Get All List”按钮,会将当前站点下的所有列表都读取出来并设置了响应的超链接属性,点击“Hide List”按钮则将之隐藏(实际上就是个Div)
代码非常的直接,只说明一个点,getEnumerator()以及moveNexst(), get_current()等JavaScript函数的使用为遍历集合提供了很好的方法 。 源代码: 复制代码 代码如下: function getLists(){ var clientContext = new SP.ClientContext(); var oWebSite = clientContext.get_web(); listCollection = oWebSite.get_lists(); clientContext.load(listCollection); clientContext.executeQueryAsync(Function.createDelegate(this, this.onGetListsSucceeded), Function.createDelegate(this, this.onGetListsFailed)); } function onGetListsSucceeded(){ var str = ""; var listsEnumerator = listCollection.getEnumerator(); while(listsEnumerator.moveNext()){ var objList = listsEnumerator.get_current(); str += "<a href=" + "http://localhost" + objList.get_parentWebUrl() + objList.get_defaultViewUrl() + ">" + objList.get_title() + "</a>" + "<br/>"; } document.getElementById("lists").innerHTML = str; } function onGetListsFailed(sender, args){ alert(Request failed. + args.get_message() + \n + args.get_stackTrace()); } CAML查询: 这里面提供了两种方式查询,一个按DueDate,一种按Title,当然功能可以设计的更加有利于用户使用些,Demo里就不做过多渲染 。点击Search就可以进行数据的查询,有一点小发现,如果使用<asp:calendar/>控件的时候选择好日期会导致页面postback,SharePoint里面至少有两种解决方案:
做了一段对控件显示的控制,选择Date则出现输入Date的控件,选择Title则出现输入Title的控件,本来想用JQuery的方法,后来一下没想起来JQuery的Selector写法,半土不洋的用了下面的方法结合控制: 复制代码 代码如下: <script type="text/javascript"> function changeQueryMethod(){ var method = $("select[id=selectQueryMethod]").val(); if(method == Title){ document.getElementById(querybytitle).style.display = "inline"; document.getElementById(querybyDate).style.display = "none"; } else{ document.getElementById(querybytitle).style.display = "none"; document.getElementById(querybyDate).style.display = "inline"; } } </script> 关于CAML查询的细节本身也不做过多说明,如果有兴趣可以参见拙文(http://www.cnblogs.com/johnsonwong/archive/2011/02/27/1966008.html),这是一篇针对2007版本的CAML,在2010里有了很多增强,譬如跨列表Joint查询等,随后会发布相应2010的版本 。 需要注意的知识是: 里面使用了对field的查询,注意相关API的调用; ClientContext里面对若干个结果集进行操作,但需要调用Load对不同结果集进行加载:clientContext.load(fieldCollection);clientContext.load(listItemCollection); 如果有需要读取的字段值需要在CAML查询XML里面显示说明,否则不会返回到结果集里,这也是出于对性能的考虑 复制代码 代码如下: function search(){ var clientContext = new SP.ClientContext(); var oWebSite = clientContext.get_web(); var list = oWebSite.get_lists().getByTitle("Tasks"); fieldCollection = list.get_fields(); var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml( "<View><Query><Where><Gt>" + "<FieldRef Name=DueDate />" + "<Value Type=DateTime>2008-01-1T00:00:00Z</Value>" + "</Gt></Where></Query><ViewFields>" + "<FieldRef Name=\"Title\" /><FieldRef Name=\"Body\" />" + "<FieldRef Name=\"DueDate\" />" + "</ViewFields></View>"); listItemCollection = list.getItems(camlQuery); clientContext.load(fieldCollection); clientContext.load(listItemCollection); clientContext.executeQueryAsync(Function.createDelegate(this, this.onSearchListSucceeded), Function.createDelegate(this, this.onSearchListFailed)); } function onSearchListSucceeded(){ var str = ""; var listItemEnumerator = listItemCollection.getEnumerator(); var fieldsEnumerator = fieldCollection.getEnumerator(); while(listItemEnumerator.moveNext()){ var oListItem = listItemEnumerator.get_current(); str += "Item " + oListItem.get_id() + ":" while(fieldsEnumerator.moveNext()){ var oField = fieldsEnumerator.get_current(); str += oField.get_staticName() + "<br/>"; } str += "<br/>"; } document.getElementById("lists").innerHTML = str; } function onSearchListFailed(sender, args){ alert(Request failed. + args.get_message() + \n + args.get_stackTrace()); } 操作文件: 遗憾的是在ECMAScript里面无法上传文件,虽然有SP.File对象,但更多的是对获取回来的SP.File对象进行操作 。 |