SharePoint 2013 应用开发实战
上QQ阅读APP看书,第一时间看更新

3.1 .NET客户端对象模型

.NET客户端对象模型是在SharePoint 2010引入的。在之前的版本,要想在客户端上和SharePoint通信,只能通过Web Service。Web Service使用起来并不方便,.NET客户端对象模型的推出,使程序员可以使用熟悉的对象模型来和SharePoint进行远程交互。

3.1.1 环境准备

使用.NET客户端模型的时候,Visual Studio可以在客户端机器上。本节会讲解如何在APS.NET网站里调用.NET客户端模型。在开始编码之前,需要在SharePoint和Visual Studio中做一些准备。

首先到SharePoint中,打开一个站点,创建一个通知列表,并且创建一些列表项,如图3-1所示。

图3-1 通知列表

然后准备Visual Studio环境。

.NET客户端对象模型的API文件存储在SharePoint服务器的C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI目录下,找到Microsoft.SharePoint.Client.Runtime.dll和Microsoft.SharePoint.Client.dll,拷贝到客户端机器上。

这里会以一个ASP.NET为宿主运行代码,读者也可以选择Windows窗体程序或者控制台程序。

打开Visual Studio,新建项目,选择“ASP.NET Web应用程序”,如图3-2所示。

图3-2 新建项目

在图3-3中选择空项目模板。

图3-3 选择空项目模板

这样一个空的项目就创建出来了。下一步是添加对SharePoint DLL的引用。在解决方案窗体里,右击“引用”,选择添加引用,在弹出的窗体里,选择“浏览”,并找到拷贝过来的两个SharePoint DLL文件,如图3-4所示。

图3-4 添加引用

引入之后,选中引入的文件,在属性窗体里,把“复制本地”改为True。这个选项能够确保在发布站点的时候,引入的dll文件能一起发布,如图3-5所示。

图3-5 复制本地属性

然后选中项目,右击,选择“添加”,在下一级菜单里选择Web窗体,命名为SharePointWeb。新建好之后,选中这个Web窗体,右击,选择设置为起始页,方便以后调试。

打开SharePointWeb.aspx.cs,加上对SharePoint客户端命名空间的引用:

    using Microsoft.SharePoint.Client;

这样开发环境就准备完毕了。

3.1.2 ClientContext

在.NET客户端对象模型中,ClientContext是一切对象的入口,因此首先要初始化这个对象。ClientContext的初始化方法如下:

    ClientContext context = new ClientContext("http://mysiteurl");

传给了ClientContext站点的URL还不够,就像在浏览器里登录SharePoint一样,还需要提供用户名密码。

    context.Credentials = new NetworkCredential("username", "password", "domain");

然后就可以获取Site和Web对象了,从而进一步获取到List、ListItem。

.NET客户端对象模型和服务器端对象模型的结构是一样的,但是在命名上去掉了SP前缀,表3-1是对照表:

表3-1 .NET客户端对象模型和服务器端对象模型的比较

3.1.3 Site和Web对象

首先在SharePointWeb.apsx上面添加几个Label控件,用来显示站点信息:

    <body>
       <form id="form1" runat="server">
       <div>
       网站标题:<asp:Label runat="server" id="webTitle" ></asp:Label><br/>
   网站说明:<asp:Label runat="server" id="webDescription"></asp:Label><br/>
   </div>
      </form>
    </body>

1.获取Site和Web对象

获取Site的方法如下:

    Site site = context.Site;

在客户端对象模型中,对网站集的操作是很弱的,基本上没有什么功能,这也是出于安全考虑。

获取网站集的顶层网站:

    Web web = site.RootWeb;

和服务器端对象模型不同,获取Web对象不一定要先构造Site对象,可以通过ClientContext对象直接获取。

    Web web = context.Web;

下面的代码演示如何获取Web的标题和说明,并显示在页面上。

在SharePointWeb.aspx.cs的Page_Load方法里面,添加如下代码:

    protected void Page_Load(object sender, EventArgs e)
    {
              ClientContext context = new ClientContext("http://mysiteurl");
              context.Credentials = new NetworkCredential("username", "pwd",
"domain");
              Web web = context.Web;
              context.Load(web);
              context.ExecuteQuery(); //只有执行ExecuteQuery才会和SharePoint通信
              webTitle.Text = web.Title;
              webDescription.Text = web.Description;
    }

按F5键,运行结果如图3-6所示:

图3-6 查询站点信息的运行结果

使用.NET客户端对象模型,有以下几点需要注意:

● 通过ClientContext获取到的Site/Web对象,是不包含任何实际属性的,需要先调用Load,再调用ExecuteQuery方法,才会去和SharePoint通信,获取信息。

● Site和Web对象,不需要使用Using或者Dispose手动释放。

● 为了减少给服务器造成的压力,以及不必要的网络数据传输,应该尽量减少调用ExecuteQuery的次数,并且每次Load的时候只Load需要的信息。

在上面的例子里,Load了整个Web对象,但是实际上只使用了Title和Description两个属性,因此可以按照下面的代码优化,将context.Load(web)替换成:

    context.Load(web, w => w.Title, w => w.Description);

上面的代码用到了Lambda表达式,因此要添加System.Linq的命名空间的引用。

2.更新站点属性

下面的代码演示如何更新Web对象的属性:

    web.Title = "研发部门站点";
    web.Description = "这个是研发部门站点,可以在这里分享文档和发起讨论和查看通知。";
    web.Update();
    context.ExecuteQuery();

这里需要注意的是,在更新SharePoint对象(调用Update方法)时,必须要调用context.ExecuteQuery();方法才会起作用。

再次把标题和说明显示在页面上,如图3-7所示:

图3-7 更新站点信息后的运行结果

3.建新站点

创建新的站点需要WebCreationInformation对象。这个也是和服务器端对象模型不一样的地方。下面的代码添加一个新的站点,并显示在页面上:

    WebCreationInformation creation = new WebCreationInformation();
    creation.Url = "serverteam";
    creation.Title = "Server Team的站点";
    creation.Description = "这个是研发部门下属Server小组的站点";
    Web newWeb = web.Webs.Add(creation);
    context.Load(newWeb, w => w.Title, w => w.Description);
    context.ExecuteQuery();
    webTitle.Text = newWeb.Title;
    webDescription.Text = newWeb.Description;

显示结果如图3-8所示:

图3-8 添加站点的运行结果

3.1.4 List对象

仿照前面的步骤,添加一个名为SharePointList.aspx的窗体,并在SharePointList.aspx.cs中的命名空间部分添加对Microsoft.SharePoint.Client和System.Linq的引用。在SharePointList.aspx中添加两个textbox:

    <body>
       <form id="form1" runat="server">
       <div>
       列表集合:<br/>
       <asp:TextBox runat="server" id="allLists"
          TextMode="MultiLine" Height="300" Width="220" >
       </asp:TextBox><br/>
        联系人列表栏:<br/>
       <asp:TextBox runat="server" id="contactListFields"
          TextMode="MultiLine" Height="300" Width="220" >
       </asp:TextBox><br/>
       </div>
       </form>
    </body>

1.获取列表信息

要获取到列表对象,同样需要先调用Load方法,在Load方法里面,指定需要获取的属性,比如标题,列表项个数,创建时间等,然后再调用context.ExecuteQuery();。

下面的代码演示如何通过Web对象获取站点里面的List的属性并显示在页面上。

    Web web = context.Web;
    context.Load(web.Lists,
    lists => lists.Include(list => list.Title,
                        list => list.ItemCount,
                        list => list.Created));
    context.ExecuteQuery();
    foreach (List list in web.Lists)
    {
          allLists.Text +=list.Title + ":" + list.ItemCount+"\r\n";
    }

运行结果如图3-9所示:

图3-9 列表标题和列表项个数

2.新建列表

创建新的列表需要借助于ListCreationInformation对象。

下面的代码演示如何新建一个联系人列表:

    ListCreationInformation creationInfo = new ListCreationInformation();
           creationInfo.Title = "联系人";
           creationInfo.TemplateType = (int)ListTemplateType.Contacts;
           List newlist = web.Lists.Add(creationInfo);
           newlist.Description = "查看本部门的联系人信息";
           newlist.Update();
    context.ExecuteQuery();

同样,在调用完newlist.Update()之后,要调用context.ExecuteQuery()才能把新建请求提交给SharePoint。

在SharePoint里面,可以看到新建了一个联系人的列表,如图3-10所示。

图3-10 添加列表的运行结果

3.获取列表栏的信息

下面的代码演示如何获取列表里面所有的栏的名字和类型:

    List contactlist = context.Web.Lists.GetByTitle("联系人");
    context.Load(contactlist.Fields);
    context.ExecuteQuery();
    foreach (Field field in contactlist.Fields)
    {
         contactListFields.Text += field.Title + ":" + field.TypeDisplayName +
"\r\n";
    }

结果如图3-11所示。

图3-11 列表的栏和类型

4.添加新栏

下面的代码演示如何给列表添加一个数字类型的栏,并且值的范围为15~100:

    List contactlist = web.Lists.GetByTitle("联系人");
    Field field = contactlist.Fields.AddFieldAsXml("<Field
    DisplayName='年龄' Type='Number' />",
                                                 true,
                                                 AddFieldOptions.DefaultValue);
              FieldNumber fldNumber = context.CastTo<FieldNumber>(field);
              fldNumber.MaximumValue = 100;
              fldNumber.MinimumValue = 15;
              fldNumber.Update();
              context.ExecuteQuery();

这里用到了CastTo方法,将Field基类的对象,转换成具体的列表类型对象。

5.删除列表

代码如下:

    List list = web.Lists.GetByTitle("MyListTitle");
    list.DeleteObject();
    context.ExecuteQuery();

3.1.5 Listitem对象

对列表项的常见操作也是增删改查。

1.查询列表项

查询列表项,要借助于CamlQuery对象来实现,下面的例子演示如何查询前100个列表项:

    List contactlist = web.Lists.GetByTitle("联系人");
    CamlQuery query = CamlQuery.CreateAllItemsQuery(100,new
string[]{"Title","Email"});
    Microsoft.SharePoint.Client.ListItemCollection items = list.GetItems(query);
    context.Load(items);
    context.ExecuteQuery();
    foreach (Microsoft.SharePoint.Client.ListItem listItem in items)
    {
                 allItems.Text += listItem["Title"] + "|" + listItem["Email"] +
"\r\n" ;
    }

此段代码把前一百个联系人的姓和邮箱显示在页面上,结果如图3-12所示:

图3-12 显示列表项

在查询列表项的时候,有以下几点需要注意:

● 在CreateAllItemsQuery方法里定义返回条目数和栏(也可以使用CAML语言),以减少数据传输。

● 上面的代码包含了列表项和文件夹(Team A是一个文件夹),以及所有子文件夹里面的列表项的。如果只想查询特定的文件夹,需要给query.FolderServerRelativeUrl赋值。

● 可以使用CAML语言来定义查询的筛选条件,排序等。

2.新建列表项

新建一个列表项需要借助ListItemCreationInformation类。还是以上面的联系人列表为例:

    ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
    Microsoft.SharePoint.Client.ListItem newItem = list.AddItem(itemCreateInfo);
    newItem'"Title"' = "张";
    newItem'"FirstName"' = "三";
    newItem'"Email"' = "zhang.san@contoso.com";
    newItem.Update();
    context.ExecuteQuery();

这里要注意一点,栏的名字一定要用内部名称,而不是在页面上看到的名称。比如“姓氏”的内部名称是“Title”,而“名字”的内部名称是“FirstName”。

如何查看一个栏的内部名字呢?进入到列表设置页面,在栏的部分,选中一个栏,右键查看属性,末尾的属性就是内部名称,如图3-13所示:

图3-13 查看栏内部名称

3.更新列表项

代码如下:

    listItem'"Company"' = "Contoso";
    listItem'"JobTitle"' = "Manager";
    listItem.Update();
    context.ExecuteQuery();

4.删除列表项

代码如下:

    listItem.DeleteObject();
    context.ExecuteQuery();

5.新建文件夹

新建文件夹的过程和新建列表项的类似,但是要指定UnderlyingObjectType为Folder:

    ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
    itemCreateInfo.UnderlyingObjectType = FileSystemObjectType.Folder;
    Microsoft.SharePoint.Client.ListItem newItem = list.AddItem(itemCreateInfo);
    newItem["Title"] = "Team A";
    newItem.Update();
    context.ExecuteQuery();

3.1.6 使用.NET客户端对象模型的最佳实践

● 在做任何操作之后,一定要调用context.ExecuteQuery(),才能把修改提交到SharePoint端。

● 不能使用没有获取到的属性。

● 尽量减少和SharePoint交互的次数。

● 在请求SharePoint数据之前,限制查询的范围,比如只请求需要的属性或者列表项。