• Windows SharePoint Services对象模型


    作为一个应用原型系统,SharePoint提供了很多强大的应用及管理功能,但是,在实际的应用中,这些原有的功能很难满足用户的需求。因此,SharePoint也提供了一套非常完整的对象模型作为底层接口,以此为基础进行二次开发。
    Windows SharePoint Services(以下简称WSS)作为SharePoint Portal Server(以下简称SPS)的基础部分,是在开发过程中使用最多的一套体系。因此,在本书开发部分的开始,使用一章的篇幅来介绍WSS的对象模型体系,以及一些简单的应用。
    WSS提供了非常完善的一套对象模型体系,大致整个的Web服务器(SPWebServer类)、小到一个文件的版本信息(SPFileVersion类),以及一些网站的设置,都可以通过WSS对象模型来进行访问或修改。此外,为了弥补.NET类库在该环境中的一些不足,在SharePoint中也提供了一些常用的功能的函数,它们被封装在Microsoft.SharePoint.Utilities命名空间中。
    通过使用SharePoint的对象模型,可以完成几乎所有的功能,但是在有些时候,由于SharePoint本身的限制(例如严格的权限控制),有一些功能仅使用对象模型是很难完成甚至无法完成的。所以,在考虑用户需求和设计方案的时候,也应该尽可能地考虑到实现的难易程度。
    在WSS对象模型体系中,提供了如下一些命名空间(namespace):
    • Microsoft.HtmlTrans.Interface
        提供一个接口,用来将文档库中的某些文件以Html的形式显示到客户端,这样在客户端没有安装相应文件的浏览软件的时候,也可以查看这些文件;
    • Microsoft.SharePoint
        该命名空间是最常用的一个命名空间,其中提供了WSS中关于网站内容的基本的对象模型,例如网站、列表、文件和用户等,本章也主要是围绕这一命名空间进行介绍;
    • Microsoft.SharePoint.Administration
        该命名空间中主要提供了WSS网站管理和参数设置的一些类;
    • Microsoft.SharePoint.Dsp
        该命名空间以及之下的几个命名空间提供了一些WSS数据搜索用的接口;
    • Microsoft.SharePoint.Meetings
        该命名空间提供了对会议室网站进行操作的一些类;
    • Microsoft.SharePoint.Security
        该命名空间提供了WSS中自定义权限管理相关的类;
    • Microsoft.SharePoint.SoapServer
        该命名空间提供了关于WebPart和WebPart页相关的WebService类;
    • Microsoft.SharePoint.Utilities
        该命名空间提供了一些网站中常用的功能,主要是扩充.NET类库中的一些功能;
    • Microsoft.SharePoint.WebControls
        该命名空间提供了一些WSS中特有的Web控件类;
    • Microsoft.SharePoint.WebPartPages
        该命名空间提供了Web部件和Web部件页相关的类,其中Web部件(WebPart)是SharePoint开发中一个重点的环节,我们将在第11章中对其进行详细地叙述;
    • Microsoft.SharePoint.WebPartPages.Communication
        该命名空间提供了对Web部件通信的支持。
    以上这些命名空间和类库封装在Microsoft.SharePoint.dll中。
     
    由于篇幅的关系,在本章中只介绍最基本的一些对象模型的使用,只涉及到Microsoft.SharePoint这一命名空间。其他对象模型的使用方法请参照SDK。
        为了便于实现和观察,也便于避开Web环境中一些复杂的机制和权限控制,本章和下一章的示例代码,均使用命令行(Console)方式完成。程序需要直接运行在装有WSS或SPS的服务器上,并且默认操作者具有网站管理员的权限。此外,本章和第10章着重讲解功能和某些注意事项,因此在介绍对象模型的时候,只介绍最常用的一些属性和方法,并且在每部分的最后给出一个示例说明该对象模型的使用方法。更全面的类库、属性和方法的介绍,以及更加详细的示例程序,请参考SDK中对应的章节。
    本书中的代码均使用C#语言编写,在WSS或SPS环境中经过测试通过。
        在绝大多数的WSS使用场景以及部分SPS的使用场景中,“网站”是使用得最多的一个对象,这是因为在WSS的体系结构中,几乎所有的内容(包括用户、列表、文件系统等)都是依附于网站之上的,这一点在对象模型中也能很明显地体现出来。
    在WSS的结构中,网站被划分为Site(网站集)和Web(网站)这两种概念。
     
    Site和Web的区别与联系
        顾名思义,网站集是网站的集合体,在WSS中,Site的主要用处是管理网站,在对象模型中,Site所对应的SPSite除了网站的集合(SPWebCollection)外几乎不包含任何的信息,所有的信息都是储存在Web所对应的SPWeb这一对象模型中的,Web才是真正的内容承载者。
        在SharePoint的最初设计理念中,将网站集称为Web,而网站称为Site,这一点从SDK中的SharePoint体系结构图中可以看出来。
        但是,在设计对象模型的时候,却又将网站集的对象模型称为SPSite(即SharePoint Site),而网站的对象模型称为SPWeb。因此在SDK的代码示例中经常可以看到例如“SPSite web;”以及“SPWeb site;”这样的变量命名方法,这对于初学者来说是非常容易引起混淆的。
        作为开发的参考,为了便于说明,以及和对象模型的统一,本书中所指的Site均为网站集的概念(对应于SPSite),而Web均为网站的概念(对应于SPWeb),请读者注意。
     
    SPSite的使用
        SPSite作为网站集对应的对象模型,其主要的用处是获取某个特定的网站,它最常用的几个功能如下:
        构造函数
            SPSite的构造函数有两种,分别以Site的url和Guid作为参数。
            在SharePoint对象模型中,大部分对象都拥有一个Guid作为它唯一的标识符,通过这个Guid可以获取该对象的实例,例如Site(SPSite)、Web(SPWeb)、列表(SPList)、视图(SPView)以及SPS中的区域(Area)、门户列表(AreaListing)等。但也有一些是采用整型作为标识符的,例如列表项(SPListItem)、角色(SPRole)和用户(SPUser)等。
     
        AllWebs属性
            该属性是一个SPWebCollection类型的变量,通过这个属性,便可以获取到该网站集中的所有网站,包括一个顶级网站和它下面的所有子网站。然后通过以下三种形式之一,便可以得到某个特定的SPWeb的对象:
    • webs[int index]:根据在该集合中的下标获取一个Web;
    • webs[string url]:根据Web的相对url(相对于包含该网站的Site)获取Web;
    • webs[Guid guid]:根据唯一标识该Web的guid获取。
            在WSS对象模型中,集合(Collection)是一个比较重要的概念,它实际上是一种对象的存储方式(即.NET框架中集合的概念)。一般来说SPxxxCollection便是SPxxx这个类所对应的集合类,例如SPWebCollection、SPListCollection和SPFileCollection等。但是应该注意到的是,SPSiteCollection并不是包含在Microsoft.SharePoint命名空间中的类,而是在Microsoft.SharePoint.Administration这一命名空间中的,这也说明了Site的主要意义在于网站本身的管理,而非网站内容的管理。
     
        RootWeb属性
            该属性是一个SPWeb类型的变量,它所对应的对象是该网站集中的顶级网站,通过它可以逐步获得该网站级中的层级结构。(关于顶级网站和子网站的概念,请参考本书中“2.1.2Windows SharePoint 站点架构简介”部分。)
     
        OpenWeb函数
           该函数返回一个SPWeb类型的变量,通过该函数可以获得该网站集中一个特定的网站。它有以下三种使用形式:
    • OpenWeb():在命令行模式中,该方法返回网站级中的顶级网站对象;但是在网络环境中使用该方法会有不同的效果,详见第11章11.3小节“WebPart编程中的对象模型”;
    • OpenWeb(Guid guid):返回该guid所对应的网站对象;
    • OpenWeb(string url):返回该url所对应的网站对象,注意该url为相对地址(相对于服务器根路径或者网站集根路径)。
    【示例9-1】 SPSite的基本使用。
    在这个示例中,展示了SPSite的基本用法,包括上面所提到的几个重要功能:
    using System;
    using Microsoft.SharePoint;
     
    namespace WSSModelObject
    {
        class Example1_1
        {
            [STAThread]
            static void Main(string[] args)
            {
                // 使用构造函数创建网站集对象
                SPSite site = new SPSite("http://localhost");
                // 获取根网站信息
                Console.WriteLine("Root:" + site.RootWeb);
                // 遍历网站集中的所有网站
                Console.WriteLine("All Webs in site:");
                foreach(SPWeb web in site.AllWebs)
                {
                    Console.WriteLine(web);
                }
                // 打开某个特定的网站
                try
                {
                    SPWeb web = site.OpenWeb("subweb1");
                    Console.WriteLine(web);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
        在编写程序的过程中,合理地使用try-catch语句是一种良好的编程习惯。SharePoint是一套相对庞大的对象模型体系,在编写程序的过程中,难免会出现预料之外的问题,因此应该尽可能对所有可能出错的语句进行try-catch,如果有必要,捕获每种特定的异常,并提供更加友好的出错信息,使得程序更加人性化。在本书中,为了节省篇幅,除非特殊的需要和说明,在后面的示例程序中一般不进行try-catch处理,请读者注意。
        编写SharePoint的程序需要在引用中添加Microsoft.SharePoint.dll,如果是在安装了WSS的机器上,在VS.NET中添加引用界面选择Windows SharePoint Services即可,也可以将dll复制到其他的机器上再引用(但是仍然需要在装有WSS的机器上才能运行),该dll的默认安装路径为:C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\ISAPI。在本书后续章节中除非特殊情况,不再使用完整的代码,而使用代码片段作为示例。
     
        SPWeb的使用
        在一般的应用场景下,SPWeb是使用最多的一个对象模型,因为几乎所有的WSS的内容都是依附于SPWeb对象的,在编程中也是使用SPWeb来获取其他的对象模型。而获取SPWeb对象的方法在本章9.2.2小节“SPSite的使用”中已经有所提及,就不在这里重复了。
    大多数和WSS相关的内容都是通过使用SPWeb的一些成员变量来获取的,这些成员变量主要有:
    • AllUsers:网站内的所有成员,以及通过域组(domain group)来浏览网站的用户;
    • Files:网站下的所有文件;
    • Folders:网站下的所有目录;
    • Groups:所有跨网站用户组;
    • Lists:网站下的所有列表;
    • ListTemplates:网站下的所有列表模板;
    • Permissions:网站下的权限;
    • Roles:网站下的所有角色;
    • Users:属于该网站的所有用户;
    • Webs:该网站的所有子网站。
        通过使用这些成员变量,就可以获取到相应内容的对象集合(Collection),进而获取需要的内容。
        此外,SPWeb的某些成员变量对应于该网站的一些属性,例如:
    • AllowAnonymousAccess:网站是否允许匿名访问(只读);
    • Author:网站的创建者(只读);
    • Created:网站的创建时间(只读);
    • CurrentUser:当前的用户(只读);
    • ID:唯一标识该网站的Guid(只读);
    • IsRootWeb:该网站是否为顶级网站(只读);
    • ParentWeb:该网站的父网站(只读);
    • Site:该网站所属的网站集(只读);
    • Title:该网站的标题;
    • Url:该网站的url(绝对路径)(只读);
    • WebTemplate:该网站的模板(只读)。
          SPWeb对象还提供了一些方法,例如:
    • GetFile:通过url获取一个文件的对象(SPFile);
    • GetFolder:通过url获取一个目录的对象(SPFolder);
    • GetListOfType:获取特定类型的列表的集合;
    • GetSubwebsForCurrentUser:获取该网站的子网站(可以指定模板);
    • GetViewFromUrl:通过url获取一个列表的视图(SPView);
    • SaveAsTemplate:将网站保存为模板;
    • SearchDocuments:搜索网站的文档库(需要开启全文检索功能);
    • SearchListItems:搜索列表条目;
    • Update:使网站属性的修改生效。
        在SharePoint的对象模型中,一些比较重要的对象都会拥有Update方法(例如SPWeb、SPList、SPField和SPListItem),在修改这些对象的属性时,只有在调用Update方法之后,这些修改才会真正生效。仅限普通属性,不包括集合类的属性,比如SPWeb.Lists中添加或删除一个列表,不需要调用SPWeb.Update方法。这一点需要特别引起注意 。
    【示例9-2】 得到一个网站集中的所有网站,并输出它们的标题、url、父网站及子网站。
    SPSite site = new SPSite("http://localhost");
    foreach(SPWeb web in site.AllWebs)
    {
        Console.WriteLine("Title: " + web.Title);
        Console.WriteLine("Url: " + url); 
        Console.WriteLine("ParentWeb: " + web.ParentWeb);
        Console.Write("SubWebs: ");
        foreach(SPWeb subweb in web.Webs)
            Console.Write(subweb.ToString() + " ");
        Console.WriteLine();
    }
        一个小技巧:在.NET对象模型中,每个类都会有ToString函数(继承自Object类),一般来说每个类也都会对这个方法进行重写。SPWeb的ToString方法一般情况下就是返回了SPWeb.Title这个属性。在大多数字符串操作过程中,一个对象的ToString方法是可以被隐式调用的(例如示例9-1中就使用了这个特性),在不知道该对象是否为空(null)的时候,如果显式调用ToString方法会造成一个异常(NullReferenceException),但是在隐式调用的时候便不会产生这个异常,如果仅是作为输出的需要,隐式的调用要比显式的调用更加方便。
        在示例9-2中,输出每个网站的父网站,但是对于顶级网站来说,其父网站为空,如果显示调用的话,便会出现异常,采用隐式调用就可以避开这个问题,只显示一个空的字符串。
        示例9-2中使用了三种输出网站标题的方法:SPWeb.Title属性,隐式调用SPWeb.ToString方法,显式调用SPWeb.ToString方法。
     
    列表相关的对象模型
        在SharePoint中,列表(List)是一个非常强大的功能。它可以方便地自定义列表的结构,添加和删除各种类型的字段,也可以设置计算字段和引用字段,也可以设置列表条目的审批功能,同时列表还提供了多种可以自定义的视图,对列表的数据进行筛选或者排序。本节主要介绍列表相关的对象,包括列表(SPList)、列表视图(SPListView)、列表字段(SPField)和列表条目(SPListItem)。
        SPList的使用
        在使用列表的功能之前,通常都需要首先获取该列表对象,获取SPList的主要方法是通过访问SPWeb.Lists这一SPListCollection类型的属性。从该集合中获得一个特定的列表对象有如下三种方法:
    • lists[string name]:通过该列表的名称获取;
    • lists[Guid guid]:通过唯一标识该列表的Guid获取;
    • lists[int index]:通过列表在该列表集合中的下标来获取
        在网站上添加列表,也是通过SPListCollection对象来完成的。添加一个列表通过调用SPListCollection.Add方法来完成,创建成功之后,会返回新列表的Guid。该方法提供了如下三种形式:
    • Add(string title, string description, SPListTemplate template):
        前两个参数分别指定列表的名称和简介,第三个参数是一个SPListTemplate型变量,指定该列表创建时所需要的列表模板对象,该对象可以通过SPWeb.ListTemplates属性获得;
    • Add(string title, string description, SPListTemplateType type):
        前两个参数指定列表的名称和简介,第三个参数使用SPListTemplateType型枚举指定列表模板,枚举中所包含的都是网站默认拥有的基本类型的列表模板,如果要创建一个自定义的列表,请使用SPListTemplateType.GenericList作为该参数;
    • Add(string title, string description, SPListTemplate template, SPDocTemplate docTemplate):
        该方法会创建一个文档库(一种特殊的列表),前两个参数分别指定列表的名称和简介,第三个参数制定列表的模板对象,第四个参数指定文档库的模板对象,该参数是一个SPDocTemplate类型的变量,可以通过SPWeb.DocTemplates属性获得。
     
        删除列表时,通过调用SPListCollection.Delete方法来完成,该方法只有一种形式:
    • Delete(Guid guid):通过列表的Guid删除该列表。
     
        SPList类有如下一些常用的属性:
    • BaseTemplate:该列表所对应的列表模板(只读);
    • BaseType:该列表的基础类型(只读);
    • DefaultView:该列表的默认视图对象(只读);
    • EnableAttachments:该列表是否允许添加附件;
    • EnableModeration:该列表是否开启审批功能;
    • Fields:列表字段的集合(将在下文进行详细介绍);
    • Forms:列表表单的集合,主要有浏览、添加和修改几个页面(只读);
    • ID:标识该列表的唯一的Guid(只读);
    • Items:列表条目的集合(将在下文进行详细介绍);
    • ParentWeb:列表所在的网站对象(只读);
    • Title:列表的标题;
    • Views:该列表的视图的集合(将在下文进行详细介绍)(只读)。
        这其中值得注意的是BaseTemplate与BaseType的区别:BaseTemplate是生成列表的模板,例如“链接”和“联系人”等,每个模板中都默认设置了一些独有的字段,该属性为SPListTemplateType型的枚举类型,默认这些模板的字段设置可以在SDK的“Field Tables for Default Lists”一节中找到;它的具体位置为Microsoft Windows Share Point Services?Appendix?Field Tables for Default Lists,而BaseType则是列表的基础类型,例如“讨论区”、“文档库”等,每种基础类型的列表都提供了一些普通列表所不具备的特殊的功能,该属性为SPBaseType型的枚举类型。
    修改列表属性后,通过调用SPList.Update方法使修改生效。
    【示例9-3】 在该示例中创建一个联系人列表,并显示该列表添加条目页面的url。
    // 首先获取到SPWeb对象web
    SPListCollection lists = web.Lists;
    SPList newList = null;
    try
    {
        Guid id = lists.Add("DemoList", "这是一个测试列表",
                                SPListTemplateType.Contacts);
        newList = lists[id];
        SPForm form = newList.Forms[PAGETYPE.PAGE_NEWFORM];
        Console.WriteLine(form.Url);
    }
    catch
    {
        Console.WriteLine("列表添加失败");
    }
    SPView的使用
        视图在SharePoint的列表中是一个比较重要的概念,在SharePoint中,列表中所有的数据都是通过视图呈现给用户的,视图中定义了需要显示的字段,以及显示的方式,某一些特殊的列表默认拥有一些特殊的视图将数据呈现出来,例如“任务”模板列表中的“日历视图”,等等。
        除了负责数据的多样化显示,视图的另外一个重要的作用就是对数据的筛选和排序,在SharePoint环境中可以直接对视图的这些内容方便地进行修改,通过使用计算字段,可以更加丰富筛选和排序的功能。
    获取一个SPView对象有如下几种方法:
    1. 通过List.DefaultView属性得到该列表的默认视图;
    2. 通过SPWeb.GetViewFromUrl方法根据url获取到该视图,在实际使用中,可以使用这种方法先获得一个视图,再得到这个视图所在的列表的对象;
    3. 通过List.Views得到该列表的所有视图,再通过以下三种方式得到特定的视图:
      • views[string name]:通过视图的名称获取;
      • views[Guid guid]:通过唯一标识该视图的Guid获取;
      • views[int index]:通过视图在该视图集合中的下标来获取。
    添加一个视图通过调用SPViewCollection.Add方法来完成,该方法有两种形式:
    • Add(string name, StringCollection fields, string query, uint rowLimit, bool paged, bool makeDefault):
    name参数指定了视图的名称,fields参数指定了需要显示的字段名的集合,query参数指定了对数据的筛选条件,rowLimit参数指定了视图中一次所返回的列表条目的最大个数,paged参数指定了该视图是否支持翻页,makeDefault参数指定了是否需要将该视图作为默认视图;
    • Add(string name, StringCollection fields, string query, uint rowLimit, bool paged, bool makeDefault,
    • SPViewCollection.SPViewType type, bool personalView):
    前面的参数含义与上文相同,type参数指定了该视图的基本类型,personalView参数指定了该视图是否为个人视图(否则为公共视图)。
    需要注意的是,与列表的添加方法不同,视图的添加方法返回的对象是SPView的对象,而不是一个Guid。
    删除一个视图同样使用SPViewCollection.Delete方法,用视图的Guid作为参数。
    有一点需要注意的是,在使用默认页面浏览一个视图的时候,视图的翻页功能只有“下一页”而没有“上一页”,如果需要实现向前翻页的功能,需要自己编写程序来完成。
     
    SPView中常用的一些属性如下:
    • ID:标识该视图的唯一的Guid;
    • ParentList:包含该视图的列表对象(SPList);
    • PropertiesXml:该视图的基本信息,包括url、名称和类型等(只读);
    • Query:视图中对数据进行筛选的查询xml字符串;
    • SchemaXml:该视图的信息,包括基本信息和例如筛选、分组等的设置(只读);
    • Title:该视图的名称;
    • ViewFields:该视图需要显示的字段的集合;
    • Url:显示该视图所对应的url(只读);
    修改视图属性后,使用SPView.Update方法使修改生效。
    【示例9-4】 该示例中创建了一个视图,并指定了该视图的一些设置:
    // 首先获取到SPWeb对象web 
    SPList list = web.Lists["ListName"];
    SPViewCollection views = list.Views;
     
    string viewName = "View_Name";
     
    StringCollection viewFields = new StringCollection();
     
    viewFields.Add("Field1_Name");
    viewFields.Add("Field2_Name");
    viewFields.Add("Field3_Name");
     
    string query = "<Where><Eq><FieldRef Name=\"Field3_Name\"/>" + "<Value Type=\"Text\">Text</Value></Eq></Where>";
     
    views.Add(viewName, viewFields, query, 100, true, false);
    程序中的StringCollection类是在System.Collection.Specialized命名空间中。
     
    SPField的使用
        SPField对应于列表对象中的字段(Field)对象,和传统的数据表一样,SharePoint的列表也是由若干个字段所组成的,每个字段可以设置为不同的数据类型,也可以拥有不同的属性设置(例如默认值、是否隐藏、是否可以为空等)。而SharePoint列表的最大一个特点,就是字段的可定制性,不需要进行任何的编程,也不用深入数据库进行复杂的调整,仅在使用界面上就可以方便地对列表的字段进行添加、删除和修改,这种方便的特性也正是很多用户喜爱SharePoint的一个重要原因。
        获得一个SPField对象的方法主要是通过SPList.Fields属性得到所有字段,再通过以下两种方法得到特定字段的对象。
    • fields[string dispName]:根据该字段的显示名称获得
    • fields[int index]:根据该字段在集合中的下标获得。

    为列表添加一个字段有三种方法:

    • Add(string dispName, SPFieldType type, bool bRequired)
                  其中第一个参数指定该字段的显示名称,第二个参数指定该字段的类型,第三个参数指定在填写数据的时候,该字段是否为必填内容。
    • AddLookup(string dispName, Guid lookupListID, bool bRequired)
                  该方法为列表添加一个特殊的字段——“查阅项”字段,通过第二个参数指定目标列表的Guid,其余两个参数的含义和使用方法与Add方法相同。
    • AddFieldAsXml(string strXml)
                 通过一段xml的描述添加一个字段,该描述中需要包括字段等信息,实际上,这段xml描述对应于SPField.SchemaXml属性。
     
    需要特别注意的是,以上三种方法所返回的虽然都是string型的变量,但是它们的含义各不相同,Add方法返回的是显示名称,AddLookup方法所返回的是内部名称(这两者的区别稍候会进行介绍),而AddFieldAsXml方法所返回的是一段包含字段名称的xml。
     
    注意:在添加字段时,bRequired参数(对应与SPField.Required属性)指定的是在用户界面中新建、修改列表项的时候,该字段是否为必填内容。但实际上,如果我们通过对象模型来创建或修改一个列表条目的时候,该字段并不会起到任何限制作用。
     
    SPField拥有如下一些比较常用的属性。
    • DefaultFormula:计算字段的公式;
    • DefaultValue:字段的默认值,即该字段在未进行设置时的初始值;
    • Description:该字段的说明描述信息;
    • Filterable:该字段是否可以被筛选(只读);
    • Hidden:该字段是否在列表中显示;
    • InernalName:该字段的内部名称;
    • ParentList:该字段所在的列表的对象;
    • ReadOnlyField:该字段是否被只读;
    • Required:在填写数据的时候,该字段是否必填;
    • SchemaXml:该字段设置的信息;
    • Sortable:该字段是否可以被排序;
    • Title:该字段的字段名,即显示名称;
    • Type:该字段的类型,为SPFieldType类型的枚举。
        在SharePoint中,每一个字段都有两个名称,即显示名称(DisplayName)和内部名称(InternalName),它们在对象模型中对应于SPField.Title和SPField.InternalName。其中显示名称是在用户使用界面上看到的名称,虽然该名称在网站使用界面的操作中是不可重复的,但是,在使用对象模型添加字段的时候,或者内部管理的时候,可能会有一些重名的字段(其中典型的代表就是每个列表的“标题”字段);而内部名称是SharePoint列表用于内部管理的名称,它在列表中是唯一的,而且其中没有中文和空格(在保存为内部名称时,对于这些字符会进行编码)。
    在编写程序的时候下列情况中必须使用显示名称:
    • 使用SPList.Fields["name"]获取该字段对象时,必须通过显示名称。
    在下列情况中必须使用内部名称:
    • 使用SPView.ViewFields的时候,添加、删除都是通过内部名称,获取的时候也是得到内部名称;
    • 使用SPView.Query的时候,必须使用内部名称;
    • 使用SPQuery(下面会提到该类)的时候,必须使用内部名称。
    在下列情况中即可以使用显示名称,也可以使用内部名称:
    • 使用SPListItem["fieldName"]获取或设置列表项某个字段的值。
     
        上面所提到的一些属性是SPField类中的属性,也就是所有字段都拥有的一些属性,而SharePoint对象模型中,也为每一种类型的字段提供了单独的类,例如SPFieldText、SPFieldLookup和SPFieldNumber等,每一个类都有一些该类型的字段所拥有的特殊属性,这些类是SPField的子类,在使用的时候需要通过强制类型转换,将SPField类转换为对应的类型。这些类的具体使用方法由于篇幅原因不在此进行详细地介绍,请参考SDK中的有关内容。
        在使用SchemaXml属性的时候,我们会发现除了SPField以及它的子类所包含的一些属性之外,还会有一个“ColName”属性,实际上这个属性是和SharePoint列表实现的具体机制相关的,它保存的是在底层数据库的某个表中存放该字段那一列的名称。关于这一点,会在第12章高级开发中,进行比较详细的介绍。
    修改字段的属性后,通过调用SPField.Update方法使修改生效。
    【示例9-5】 为列表创建一个NumDemo字段,并指定该字段的最大值和最小值:
    // 首先获取到SPWeb对象web 
    SPList list = web.Lists["ListName"];
     
    string fieldName = list.Fields.Add("NumDemo", SPFieldType.Number, false);
     
    SPFieldNumber field = (SPFieldNumber)list.Fields[fieldName];
    field.MinimumValue = 0;
    field.MaximumValue = 100;
    field.Update();
    该示例中值得注意的是,在列表的字段集合中添加一个字段之后,没有调用list.Update方法,而在对字段本身的属性进行修改之后,调用了field.Update方法。关于对象模型中Update方法的这一点特性已经在本章9.2小节中进行说明了,在此通过示例的方式再次强调一下。
     
    SPListItem的使用
        在列表的实际操作中,最终要接触到的还是作为数据内容部分的列表条目(List Item)。一般来说,在访问列表的某个具体条目之前,都需要先获得一个列表条目的集合,在SharePoint对象模型中,提供了很多种方法来获取列表条目集合:
    最直接地获取列表条目的方法为,使用SPList.Items属性,该属性返回列表中的所有列表条目。在需要得到或者遍历所有列表条目的时候,可以使用这种获取列表条目的方法。
    如果有目的地要获得部分列表条目,可以使用SPList.GetItems方法,该方法有如下三种形式:
    • GetItems(SPView view)
                返回指定视图中的列表条目,通过这种方法可以按照视图中所指定的筛选、排序及其他的条件按照顺序返回列表条目。在返回的条目中,也只有在视图中定义过的可查看字段中的数据才可以访问到。
    • GetItems(SPQuery query)
                顾名思义,SPQuery是SharePoint中负责查询列表条目的一个类,通过定义一个查询,可以方便地获取想要得到的列表条目,SPQuery提供了两种构造函数,一种是无参数的,另外一种可以带有一个SPView类型的参数,即在指定的视图上进行二次的查找。                       SPQuery最核心的一个属性就是Query属性,它是一个字符串的类型,它通过一种特殊定义过的xml形式,即CAML(Collaborative Application Markup Language)的形式描述一个查询的条件,实际上,这个查询字符串和SPView.Query属性是相当的。在SPQuery中,也可以通过ViewFields属性来指定需要查看的字段(如果不加以指定,则查看所有字段)。在本节最后的示例中,将演示SPQuery的用法。
    • GetItems(SPQuery query, string viewID)
                指定SPQuery查询和视图,获取列表条目。需要特别注意的是,虽然第二个参数为字符串类型,但是在使用的时候需要传入的是列表视图的Guid,而不是视图的名称,而且该Guid要以一种特殊的形式传入,即两边用“{}”包围起来,全大写形式,这种形式可以通过Guid.ToString("B").ToUpper()方法得到。
                在使用SPQuery的时候,必须每使用一次都要重新进行构造(即使用new运算符重新生成一个新的对象),然后再指定Query属性。否则,如果不进行重新构造,即使指定了不同的Query属性,在每次查询的时候始终得到的是第一次指定的Query条件的查询结果。这一点非常容易被忽略。
     
    以上几种方法所返回的都是SPListItemCollection类型的列表条目集合,获得该集合后,在获得某个具体的列表条目时,有下面两种方法。
    • items[int index]:通过在集合中的下标得到该条目,这种方法多在遍历集合的时候使用;
                 也可以使用SPListItemCollection.GetItemById方法。
    • GetItemById(int id):在SharePoint中,每个列表条目都会有一个在该列表中唯一的id(int型),调用SPListItemCollection类的GetItemById方法,就可以通过该id来得到对应的列表条目。
     
        在得到列表条目之后,就可以对该条目的内容进行访问或修改了,访问条目某个字段的方法最常用的方法为:
    •      item[string fieldName],其中fieldName可以使用该字段的显示名称,也可以使用该字段的内部名称。

                   还有一点需要注意的是,该方法所返回的是一个Object类型的变量,如果需要使用该变量的话,必须要对它进行强制类型转换,在转换的时候也要特别注意,如果该条目的该字段没有填写任何内容,那么该返回值是null,如果不加以检查就进行类型转换的话,会引发一个异常(NullReferenceException)。在使用这种方法填写或修改字段数据的时候,除了DateTime类型的数据之外,可以一律使用string类型写入(但是除非特殊需要,不建议使用这种做法)。

     
        审批也是SharePoint列表的一个重要的特色,它允许一个列表条目呈现“已审批、待定、被拒绝”这三种状态,在默认视图中,只显示已审批的条目,在“我的提交”视图和“审批视图”中,可以看到其他的条目。
    在SharePoint中,一个列表条目的审批信息并非是保存在某个字段中的,而是在对象模型中对应为SPModerationInformation类,并通过SPListItem.ModerationInfomation属性来访问,该类只有两个属性。
    • Comments:审批意见。即列表管理员进行审批操作的时候所填写的意见。
    • Status:审批状态。该属性为SPModerationStatusType枚举类型,对应三种状态。
        需要注意的是,ModerationInfomation这一属性,只有当列表允许审批的时候(即列表SPList的EnableModeration属性为true的时候)才可以取得,否则,该值始终为null。
        在使用允许审批的列表的时候,获取列表条目时会有一些不同。使用SPList.Items属性只能获得该列表中状态为“已通过”的那些列表条目,要获得其他条目,则必须通过“我的提交”或“审批视图”这两个视图,使用SPList.GetItems方法来取得。开启了审批的列表都会有这两个视图存在,这两个视图SPView对象的ModerationType属性分别为“Contributor”和“Moderator”,表明属于哪一个审批的视图。
     
    在SPListItem中,还有一些比较常用的属性如下。
    • Attachments:该列表条目的附件集合;
    • File:如果该列表是文档库的话,得到该文件的对象(以上两个属性的使用请参考下一节“文件相关的对象模型”);
    • ID:在该列表中唯一标识该列表条目的整型的id;
    • ModerationInfomation:该列表条目的审批信息;
    • ParentList:该列表条目所在列表的对象;
    • Xml:以Xml的格式返回该列表条目中的所有数据。
    在列表条目的内容修改后,通过调用SPListItem.Update方法使修改生效。
    添加一个列表条目的方法非常简单,只需要调用SPListItemCollection.Add方法,该方法不需要参数,直接返回一个空的SPListItem对象,通过对该对象对各字段的内容进行修改,再调用Update方法,即可将该条目添加到该列表中。
     
    删除一个列表条目,有两种方法:
    • SPListItemCollection.DeleteById(int id)
               通过列表条目的id来删除该条目;
    • SPListItemCollection.Delete(int index)
               通过集合中的下标来删除该条目。
     
    在通过Delete方法删除一个列表中的所有条目时,注意必须使用下面这种逆序的循环方法:
    int total = items.Count;
    for(int i=total-1; i>=0; i--){
        items.Delete(i);
    
    }
    而不能正向的循环,更不能使用foreach循环来进行,在初学者中,这是一个比较常见的错误。请读者自己思考这样做的原因。
    在SPListItemCollection类中,还有一个非常有用的方法:GetDataTable方法,即:
    DataTable GetDataTable();
    该方法可以返回由这些列表条目所组成的DataTable对象,以便将数据绑定到一些显示控件(如DataGrid)上。但是注意当列表中没有条目的时候,该函数返回的是null,而不是一个有效的DataTable对象。
    【示例9-6】 通过SPQuery获得Score字段中大于等于60的列表条目,并且在这些条目的标题后加上“(合格)”字符串,然后再另一列表中,添加一个新条目,写入合格人数。
    // 首先获取到SPWeb对象web
    SPListCollection lists = web.Lists;
    SPList scoreList = lists["Score"];
    SPList passList = lists["Pass"];
     
    SPQuery query = new SPQuery();
    query.Query = "<Where><Geq><FieldRef Name='Score'/>" +
        "<Value Type='Number'>60</Value></Geq></Where>";
    SPListItemCollection items = scoreList.GetItems(query);
     
    foreach(SPListItem item in items)
    {
        string title = item["Title"] + "(合格)";
        item["Title"] = title;
        item.Update();
    }
     
    SPListItem newItem = passList.Items.Add();
    newItem["Count"] = items.Count;
    newItem.Update();
        在该例中,为了简化场景,没有考虑到不同人、不同科目的分数问题。另外,这个例子只是为了说明和列表条目有关对象模型的使用方法,在实际的应用场景中,类似于上面这种问题,可以通过视图的筛选、分组和汇总的功能在一张列表中直接完成,而且可以接受多人、多科目这种条件,分别统计每一科的合格人数,不需要进行任何编程,SharePoint中强大的视图功能便可以体现在其中。请读者自己思考视图设置的方法。
    文件相关的对象模型
     
    SPAttachmentCollection的使用
        在SharePoint的列表中,每个列表条目可以拥有0到多个附件文件(附件功能可以在列表常规设置中开启或关闭),在对象模型中,访问这些附件,则可以使用对象模型中的SPAttachmentCollection类来完成。
    使用SPAttachmentCollection.Count属性可以得到该列表条目中附件的个数,使用以下方法,则可以获得每一个附件所在的地址。
    • attachments[int index]:通过下标得到附件的文件名,这些附件实际上也是保存在SharePoint的文件系统中的,它们的url为:“List/Attachments/ItemID/FileName”,自然地,SPAttachmentCollection的对象模型中也提供了这样一个属性来访问这一串地址:
    • UrlPrefix:附件文件的前缀url地址(绝对url)。
    附件的添加和删除,和添加、删除文件的方法是一样的。
    • Add(string filename, byte[] data):第一个参数指定文件名,第二个参数指定附件内容的字节流。该文件已经存在的时候,也会返回一个异常。
    • Delete(string filename):根据文件名删除该附件。
        与添加、删除文件不同的是,因为附件操作是包含在列表条目的修改之中,所以使用Add方法和Delete方法必须调用SPListItem.Update方法才能使修改生效。为了更直接的对附件进行操作,免除Update这一麻烦,SPAttachmentCollection类中提供了AddNow和DeleteNow两个方法,它们的参数和使用与Add和Delete方法一致,只是调用完之后立刻生效,而不再需要进行Update。
        在一个列表条目生成之前,SPListItem中的一切属性都是不可用的,所以在对附件进行操作的时候尤其要进行注意,只能对已有的列表条目进行附件的操作。在添加一个新的列表条目的时候,也必须先执行SPListItem.Update,使之成为已有的列表条目,然后才能进行附件操作。
    【示例9-9】 该示例读取DemoList列表第一个列表条目的附件,并将它们保存到本地:
    // 首先获取到SPWeb对象web
    SPList list = web.Lists["DemoList"];
    SPListItem item = list.Items[0];
    SPAttachmentCollection attach = item.Attachments;
    for(int i=0; i<attach.Count; i++)
    {
        String url = attach.UrlPrefix + attach[i];
        Console.WriteLine("正在下载{0}...", url);
        SPFile file = web.GetFile(url);
        FileStream fs = new FileStream(file.Name, FileMode.Create);
        byte[] content = file.OpenBinary();
        fs.Write(content, 0, content.Length);
        fs.Close();
    }
    注意在该程序中,默认列表DemoList存在,也默认该列表中拥有至少一个列表条目。
     
    文档库
        文档库是SharePoint中非常重要的一个功能,它提供了例如签入/签出,结合Microsoft Office在线编辑、版本控制等诸多方便的功能。而在SharePoint的对象模型中文档库也是一个比较特殊的对象。
     
    在SharePoint中,文档库有三种形式:文档库、表单库、图片库。
        作为一个特殊的对象,文档库即是一个列表(List),也是一个文件夹(Folder)。这样的特性就意味着文档库既可以通过SPList对象来访问,也可以通过SPFolder和SPFile来访问,它们之间是有着内在联系和明确分工的。
    在使用SPList访问的时候,它的“FileLeafRef”(内部名称)字段保存的是文件的文件名,它可以通过定义视图和查询来查找我们所需要的某部分文件。在获得SPListItem之后,也可以通过SPListItem.File来得到该列表条目所对应的文件(SPFile)的对象。但是由于是列表的形式,在获得列表的时候是很按照文件夹的方式去获取的,这个时候就需要结合另外的类来进行操作。
        判断一个列表是否是文档库,可以通过判断SPList.BaseType属性是否为SPBaseType.DocumentLibrary来完成。而SharePoint也专门提供了一个SPList的子类——SPDocumentLibrary来访问文档库,在判断一个列表为文档库之后,可以将该对象强制转换为SPDocumentLibrary类型,在该类型中,提供了一个有用的函数:
    •     GetItemsInFolder(SPView view, SPFolder folder):指定一个列表的视图,指定一个文件夹,返回该文件夹内的文件所对应的列表条目集合对象(SPListItemCollection)。
                  同时,我们也可以通过SPList.RootFolder属性得到该文档库的根目录的对象(注意之前应把SPListCollection.IncludeRootFolder设为true)。
        在使用SPFolder和SPFile对象访问文档库的时候,可以方便地获取文档库中的层级结构,也可以得到文件的签入/签出状态和版本控制信息,也可以方便地对文件进行复制、移动和删除的操作。但是仅使用这种方法,却无法获得一个文档的审批状态。
        在判断文件夹是否为文档库时,可以通过SPFolder.ContainingDocumentLibrary属性来完成,如果该文件夹在文档库中,那么该属性会返回该文档库所在列表的Guid,可以借此获得列表对象;在判断一个文件是否在文档库中时,使用SPFile.InDocumentLibrary属性即可。在确定一个文件包含在文档库之后,通过SPFile.Item属性就可以得到对应的列表条目对象(SPListItem)。
        将SPFolder/SPFile与SPDocumentLibrary结合起来使用,可以充分地发挥SharePoint文档库的强大功能。此外,SharePoint文档库还提供了文档讨论的功能,通过ie的一个ActiveX插件来对每一篇文档进行讨论,在对象模型中也提供了SPDocDiscussion类获得该讨论的部分信息,有兴趣的用户可以参考SDK中的相关章节。
        在使用文档库的时候,尤其是在中文SharePoint系统中,特别需要注意的是,要明确“列表名称”和“目录名称”这两个不同的概念,这两者可能是不同的,例如,一个文档库的名称叫做“共享文档”(列表的名称),而它所在的url是“Shared Document”(目录的名称)。在使用SPList和SPFolder的时候,不要将这两者混淆起来。
     
    用户/权限相关的对象模型
        权限系统是SharePoint的另一大特点,在WSS中,权限可以划分到列表级,而且SharePoint的权限是详细到代码级别的,称为CAS(Code Access Security),也就是说每一个对象模型中的方法、属性的访问都会涉及到权限的问题。这也是为什么前两章都要使用命令行(Console)方式的程序作为示例,而且直接在服务器端运行的原因(正如本章一开始所说的,默认读者是以管理员的身份在服务器端进行操作)。在这样一种权限的机制上,应该说整个SharePoint环境是比较安全的,除非直接读取底层数据库,否则用户无法获得其权限之外的数据;然而在另一个角度上,这种权限的机制也比较死板,只要数据在用户的访问或修改权限之内,那么使用普通的方法也是无法真正限制用户对数据的访问和修改的。
        而在用户系统上,SharePoint可以与AD相结合,通过AD来管理、组织用户,可以说非常灵活和强大。
        一般来说,用户系统与权限系统是比较紧密地结合在一起的,SharePoint也不例外。因此,本节将两者结合起来介绍。SharePoint对象模型中与用户/权限相关的类主要有以下三个:SPPermission、SPRole、SPUser
     
    SPPermission的使用
        在SharePoint中,由于权限是深入到代码级别的,在每执行一句代码——尤其是对数据进行修改、对系统进行管理的代码——的时候,都有可能会因为当前执行者的权限不足而引发异常。虽然try-catch能够在事后检测并捕获到大部分这种异常,但是,事前的检测在代码编写的过程中有时也是必要的;而有的时候,也需要根据用户的不同权限显示出不同的信息。用户权限的检测就是通过SPPermission类来完成的。
        在介绍SPPermission类之前,有必要先简要介绍一下和权限相关的重要的枚举类型SPRights。在这个枚举类型中,列举了所有WSS网站中所用到的权限,例如创建列表条目、修改列表条目、删除列表条目等。在使用这些权限的时候,可以通过二进制掩模(Mask)的方式,将多个权限进行或(or)操作,得到一个新的包含所有用户指定的权限的SPRights变量,后文中的PermissionMask一般都是通过这种方法获得的。由于篇幅关系,这些具体的权限及其含义就不在此列出了,需要使用的时候,请读者参考SDK中的相关内容。
    另外,SharePoint也提供了SPPermissionGroup枚举类型,其中定义了每种角色的PermissionMask,在需要获取角色默认权限的时候,可以直接使用该枚举类型。
    权限都是挂靠在某个对象上的(比如网站、列表等),在访问这些对象的权限的时候,可以直接通过SPWeb.Permissions属性和SPList.Permissions属性来获得。获取某个具体的用户、角色的权限的时候,通过以下方法来取得:
    • permissions[SPMember member]
              其中SPMember是表示用户的SPUser类、表示角色的SPRole类、表示用户组的SPGroup类的一个父类。通过这种方式,可以获得某个网站(或列表)上,某个用户(或角色)的权限。
     
    添加、删除某个用户的权限的时候,同样通过SPPermissionCollection类的方法来完成:
    • Add(SPMember member, SPRights permissionMask):为某个网站成员(用户或角色)添加permissionMask中指定的权限;
    • Remove(SPMember member):删除指定网站成员的权限;
    • ResetPermissions():按照父网站的权限设置,重置该对象的权限。
    在得到一个SPPermission对象之后,可以使用它的一些属性:
    • Member:一个SPMember的对象,即拥有该权限的成员;
    • Parent:一个Object的对象,即拥有该权限的对象(SPWeb或SPList);
    • PermissionMask:具体的权限设置;
    • Xml:以xml形式描述的权限设置。
        通过将PermissionMask属性与SPRights枚举中的某些具体权限进行与(and)操作,根据操作结果是否非零,来表明该成员在该对象上是否拥有该权限。
        但是,正如本节一开始所提到的,之所以需要检查权限的设置,是因为有一些用户没有权限来进行数据的操作或系统的设置。而上面所涉及到的那些方法和属性所需要的对于权限的控制的权限,显然是“普通用户”所不具备的。好在SharePoint为我们提供了一个“普通用户”也可以执行的方法,用来检测权限,它是SPPermissionCollection中的一个方法:
    • DoesUserHavePermission(SPRights permissionMask)
             检测当前的用户是否具有参数中所描述的权限,该方法返回一个bool型的值。在执行某些语句之前,或者在需要针对不同权限用户显示不同内容的时候,通过调用这个方法,就可以明确地知道当前执行这段代码的用户,是否具有某种权限,从而再进行相应的处理。
    【示例9-10】 列举某个网站上当前用户的所有权限:
    // 首先获取到SPWeb对象web
    foreach(SPRights right in Enum.GetValues(typeof(SPRights)))
    {
        if(web.Permissions.DoesUserHavePermissions(right))
        {
            Console.WriteLine(right.ToString());
        }
    }
    读者可以使用不同的网站用户身份登录服务器运行这段代码,观察得到的结果有何不同。
    SPUser的使用
    SPUser是SharePoint中的用户类,在获取SPUser对象的时候,可以通过SPWeb.Users、SPWeb.AllUsers或者SPRole.Users来得到一个SPUserCollection,再通过以下两种方式得到用户。
    • users[string loginName]:以登录名获取到集合中的用户;
    • users[int index]:以集合中的下标获取到用户。
    也可以使用如下方法。
    • GetByID(int id):通过用户id获取某个用户的对象;
    • GetByEmail(string email):通过用户的电子邮件地址获取某个用户的对象。
    如果只需要获取到当前用户的话,也可以方便地使用SPWeb.CurrentUser属性。
    为某个集合添加、删除用户的时候,使用SPUserCollection类中的方法。
    • AddCollection(SPUserInfo[] users):添加一批用户,其中SPUserInfo是一个简单的结构,其中包含Email、LoginName、Name和Notes这四个属性,属性的含义见SPUser类的属性;
    • Remove(int index):通过集合中的下标来删除集合中的用户;
    • Remove(string loginName):通过用户的登录名来删除该用户;
    • RemoveByID(int id):通过用户的id来删除该用户;
    • RemoveCollection(string[] loginNames):通过登录名删除一批用户。
    SPUser有如下几个常用的属性。
    • Email:用户的E-mail地址;
    • ID:在当前Site上,唯一标识该用户的id(int型)(只读);
    • IsDomainGroup:该用户是否是一个域组(只读);
    • IsSiteAdmin:当前用户是否是网站管理员(只读);
    • LoginName:用户的登录名(只读);
    • Name:用户的显示名称;
    • Notes:用户的简要说明;
    • ParentWeb:该用户所在的网站(只读);
    • Roles:该用户在该网站的角色;
    • Xml:该用户信息的xml形式的描述(只读)。
        需要值得注意的是,在上述的用户信息中,只有LoginName是唯一的(也是全局唯一的),在不同的网站上,用户可能拥有不同的E-mail、显示名称和简介。
        在修改用户的属性之后,需要调用SPUser.Update方法使修改生效。
        为用户添加角色的过程,一般而言,是通过在角色中加入该用户来完成的,将在下一部分介绍这一方法。
     
     
    SPRole的使用
        SPRole对应于WSS网站中的用户角色(也称为网站用户组,即Site Group)。首先要特别提醒读者注意的是,该对象模型只能应用于WSS网站中,在SPS网站中使用该对象,则会直接引发错误,并且该错误无法被try-catch所捕获,请特别加以小心。
     
    获取SPRole的对象,一般也是先通过SPWeb.Roles属性或者SPUser.Roles属性得到一个SPRoleCollection对象,再通过以下两种形式得到特定的SPRole。
    • roles[string name]:通过角色的名称获取;
    • roles[int index]:通过集合中的下标获取;
    或者使用如下方法。
    • GetByID(int id):通过角色的id获取;
    • GetSpecialRole(SPRoleType type):一般来说,网站会默认的拥有一些特殊的角色(管理员、网站设计者、讨论参与者、读者和来宾),在对象模型中,SPRoleType枚举类型对应这五种已有的角色。该方法可以直接获得这五种特殊的角色之一。
    添加、删除角色的时候使用SPRoleCollection中的方法。
    • Add(string name, string description, SPRights permissionMask):添加一个角色,第一个参数指定角色的名称,第二个参数指定角色的描述,第三个参数指定角色所拥有的权限;
    • Remove(int index):通过在集合中的下标删除该角色;
    • Remove(string name):通过角色名称删除该角色;
    • RemoveByID(int id):通过角色的id删除该角色。
    SPRole的常用属性如下:
    • Description:该角色的描述信息;
    • ID:在该网站上唯一标识该角色的ID(int型)(只读);
    • Name:该角色的名称;
    • ParentWeb:该角色所在网站的对象(只读);
    • PermissionMask:该角色所拥有的权限;
    • Type:该角色的类型(仅对特殊角色有效)(只读);
    • Users:该角色中的用户的集合;
    • Xml:该角色的xml形式的描述(只读)。
    在修改角色的信息后,需要调用SPRole.Update方法使修改生效。
    在管理一个角色中的用户的时候,直接使用SPRole的方法(而不是在SPRole.Users属性中进行添加或删除)。
    • AddUser(SPUser user):直接通过该用户的SPUser的对象实例来添加该用户;
    • AddUser(string loginName, string email, string name, string notes):通过用户的基本信息添加该用户;
    • RemoveUser(SPUser user):删除该用户。
    【示例9-11】 获取网站中的角色,在不存在当前用户的角色中加入当前用户,然后遍历该角色中的所有用户。
    // 首先获取到SPWeb对象web
    SPUser current = web.CurrentUser;
    foreach(SPRole role in web.Roles)
    {
        Console.WriteLine("Role:{0}", role.Name);
        if(role.Type != SPRoleType.Guest)
            try
            {
                SPUser user = role.Users[current.LoginName];
            }
            catch
            {
                role.AddUser(current);
            }
     
            foreach(SPUser user in role.Users)
            Console.WriteLine("\tUser:{0}", user.Name);
    }
    在该示例中,在添加用户的时候排除掉了“来宾”这一角色,这是因为该角色一般只应用在SPS的网站当中,无法将WSS网站中的普通用户加入该角色当中。
     
        SharePoint的文件系统同样分为文件和文件夹这两大组成部分,但是与普通的asp.net编程不同的是,SharePoint中的文件和文件夹绝大部分是保存在数据库中的,只有一少部分(“_layouts”目录下的文件)是直接保存在服务器的文件系统中(这些文件默认的路径为:“C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\ LAYOUTS”)。在一般的程序编写中,极少有需要去访问“_layouts”目录下的文件,而访问其他的文件(包括网页、文档库、图片库等)都需要通过SharePoint的对象模型来完成。本节主要介绍SharePoint文件相关的对象模型SPFolder和SPFile,之后会介绍列表中附件的对象模型SPAttachmentCollection,最后用一定的篇幅对SharePoint中特殊的列表“文档库”进行一些简要地说明。
     
    SPFolder的使用
        SPFolder是SharePoint对象模型中文件夹相关的类,它的使用方法相对比较简单。获取一个SPFolder的对象可以通过SPFolderCollection使用以下两种方法获得。
    • folders[int index]:通过文件夹集合中的下标来获得;
    • folders[string url]:通过该文件夹的url来获得。
        而SPFolderCollection对象一般可通过SPWeb.Folders属性或SPFolder.SubFolders属性来获得。
        而在SPWeb和SPList的对象模型中,都有该网站(或列表)所在的根目录的信息,可以直接通过SPWeb.RootFolder属性和SPList.RootFolder属性得到。但是需要特别指出的是,SPList.RootFolder的访问默认是没有开启的,如果想通过这种方法得到一个SPFolder对象,必须先将SPListCollection.IncludeRootFolder属性设为true。
        在SPWeb中,也可以使用GetFolder方法来获得该网站中的某个文件夹对应的SPFolder对象。
    • GetFolder(string url):参数为该文件夹所对应的路径(注意不要包含最后的“/”字符)。
    • 文件夹的添加和删除同样是通过SPFolderCollection来完成的。
    • Add(string url):添加一个文件夹,参数为待添加文件夹的url,该函数成功后直接返回一个SPFolder对象;
    • Delete(string url):删除一个文件夹,参数为待删除文件夹的url。
    • 在SPFolder类中,有如下一些常用的属性。
    • ContainingDocumentLibrary:如果该文件夹是包含于一个文档库中的,那么该属性返回标识该文档库列表的Guid。该属性只读;
    • Exists:判断该文件夹是否存在,在获取一个文件夹之后(尤其是通过url的方式获取一个文件夹之后),非常有必要先判断该文件夹是否存在,因为在获取文件夹的时候,文件夹不存在并不会引发异常,而在使用一个不存在的文件夹的时候,必然会引发异常。该属性只读;
    • Files:该文件夹下的所有文件的集合;
    • Name:该文件夹的名称(只读);
    • ParentFolder:它的上一级文件夹的对象(只读);
    • ParentWeb:该文件夹所在网站的对象(只读);
    • ServerRelativeUrl:该文件夹相对于服务器根地址的url(只读);
    • SubFolders:该文件夹下所有子文件夹的集合;
    • Url:该文件夹相对于其所在网站的url(只读)。
        SPFolder也提供了两个非常有用的函数。
    • CopyTo(string newUrl):将该文件夹复制到参数所指定的url中;
    • MoveTo(string newUrl):将该文件夹移动到参数所指定的url中。
    【示例9-7】 一个简单的函数,通过递归的方法遍历某文件夹下的层级结构:
    void LookupFolders(SPFolder parentFolder, int level)
    {
        for(int i=0; i<level; i++)
    Console.Write('\t');
        Console.WriteLine(parentFolder.Name);
     
        foreach(SPFolder subFolder in parentFolder.SubFolders)
        {
            if(subFolder.Exists)
                LookupFolders(subFolder, level+1);
        }
    }
    SPFile的使用
         SPFile对应于SharePoint对象模型中的文件,它的使用方法与SPFolder类大致相似。在获取SPFile对象的时候,仍是通过SPFileCollection来进行,形式也与获取SPFolder相同。在SPWeb中,也同样提供了SPWeb.GetFile方法来获取一个文件。
    • GetFile(string url):参数为该文件所在的url。
    • 此外,对于文档库列表中的列表条目来说,也可以通过SPListItem.File来得到该文件的对象(关于文档库,稍候会进一步加以说明)。
    • 在删除文件的时候,同样使用SPFile.Delete方法。
    • Delete(string url):参数为待删除文件的url。
    • 添加一个文件与添加文件夹稍有不同,需要指定文件的内容,并且有如下三种不同的形式。
    • Add(string url, byte[] content):第一个参数指定待添加文件的url,第二个参数中以字节流的方式指定文件的内容。在指定文件url的时候,既可以使用完整的url(需要保证该目录存在),也可以只使用文件名(即添加到当前文件夹中)。使用该方法添加文件的时候,如果该url已经存在一个文件,则该函数会引发一个异常;
    • Add(string url, byte[] content, bool overwrite):与上一种形式不同,这种形式通过第三个参数来指定当文件已存在时,是否进行覆盖。当overwrite为true时,会对重名的文件进行覆盖;否则,如果出现重名的情况,仍然会引发一个异常;
    • Add(string url, byte[] content, SPUser createdBy, SPUser lastModifiedBy, DateTime timeCreated, DateTime timeLastModified):添加文件的时候,根据后4个参数,指定文件的创建者、修改者、创建时间、修改时间。但是在使用这种形式的时候需要注意,该程序的执行者必须为网站的管理员,而且该形式只有在WSS网站上有效(在SPS网站上,该方法会产生一个“Access Denied”错误)。
        以上三种方法在创建成功之后均会直接返回一个SPFile类型的对象。
        SPFile类中一些属性及其含义如下,这些属性一律为只读的。
    • Author:文件的创建者,是一个SPUser类的对象(关于该类,会在下一节中进行说明);
    • CheckedOutBy:文档库的文件允许进行签入和签出的操作,该属性为签出的用户;
    • CheckedOutDate:文件签出的时间;
    • CheckedInComment:文件签入时的评论内容;
    • CheckOutExpires:文件签出的过期时间;
    • CheckOutStatus:文件签出的状态,
    • Exists:该文件是否存在;
    • IconUrl:SharePoint为每种常用类型的文件都提供了图标,该属性中保存了该图标的图像文件的文件名(并非完整的url),这些图片一般保存在“_layouts/images/”目录下;
    • InDocumentLibrary:表示该文件是否在文档库中;
    • Item:如果该文件在文档库中,那么该属性(SPListItem类)获取该文件在该文档库列表中的列表条目对象;
    • Length:文件的大小(以字节为单位);
    • ModifiedBy:该文件的最后修改者;
    • Name:该文件的文件名;
    • ParentFolder:该文件所在的目录对象;
    • Properties:一个Hashtable型的对象,包括该文件的一些常用属性(例如创建者、创建时间、修改者、修改时间、文件大小、文件的版本等信息);
    • ServerRelativeUrl:该文件相对于服务器根地址的url;
    • TimeCreated:文件创建的时间;
    • TimeLastModified:文件最后修改的时间;
    • Url:该文件相对于其所在网站的地址;
    • Versions:SPFileVersionCollection类的对象,SharePoint的文档库可以支持文档的版本管理和控制,该属性中保存了该文件自创建以来的各个版本,同时保存了各版本的信息。(由于篇幅所限,不再一一列举SPFileVersion类的属性,有兴趣的读者请参考SDK。)
        SPFile类中也同样提供了一些方法。
    • CheckIn():将文件签入文档库;
    • CheckOut():将文件从文档库中签出;
    • CopyTo(string newUrl):将文件复制到一个新的url地址中;
    • CopyTo(string newUrl, bool overwrite):将文件复制到新的url地址中,并指定是否覆盖同名文件;
    • MoveTo(string newUrl):将文件移动到一个新的地址中;
    • MoveTo(string newUrl, bool overwrite):将文件移动到一个新的地址中,并指定是否覆盖同名文件;
    • OpenBinary():以byte[]的形式返回该文件的内容;
    • SaveBinary(byte[] content):以参数为内容,保存该文件。
    【示例9-8】 该示例中演示了从本地上传文件到文档库的过程:
    // 首先获取到SPWeb对象web
    SPFolder folder = web.GetFolder("Shared Documents");
    if(folder.Exists)
    {
        FileStream fs = new FileStream(@"C:\Demo.txt", FileMode.Open);
        byte[] content = new byte[fs.Length];
        fs.Read(content, 0, (int)fs.Length);
        folder.Files.Add("Demo.txt", content);
        fs.Close();
    }
    else{
        Console.WriteLine("Folder Not Exist!");
    }

    该程序中的FileStream类和FileMode枚举是在System.IO命名空间中。

  • 相关阅读:
    使用正则表达式验证密码长度
    创建字符串
    洛谷P1605 迷宫 深度搜索 模板!
    洛谷P5534 【XR-3】等差数列 耻辱!!!
    搜索字母a或A
    洛谷P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here
    19新生赛 质数中的质数
    洛谷P1055 ISBN号码
    洛谷P 1427 小鱼的数字游戏
    洛谷p1047 校门外的树
  • 原文地址:https://www.cnblogs.com/masahiro/p/10128079.html
Copyright © 2020-2023  润新知