地下室的流星雨
看一个人是否聪明看他的答案;看一个人是否有智慧看他的问题。

MOSS 2007构建于WSS 3.0(Windows SharePoint Services 3.0)对象的基础之上的,并且在这个基础之上,增加了诸如InfoPath Form Services、Excel Services、BDC(商业数据目录)、企业级搜索等一系列功能应用,并且还整合了微软的一个产品企业内容服务(Content Management Server 2002)。

在Windows 2003中,WSS 3.0作为一个免费组件来提供,安装后,可以进行应用的开发,只不过很多重要功能没有。MOSS 2007和WSS 3.0在一些底层的服务架构方面都是完全一致的,所以了解了WSS 3.0,就能很好地理解MOSS 2007。

通过图8-1相信读者可以理解MOSS 2007和WSS 3.0的关系。

9

图8-1  MOSS2007与WSS 3.0的关系

利用WSS 3.0对象,几乎无所不能,比如定制网站界面、管理网站设置、自定义界面、查询网站内容等。MOSS本身提供的功能,想要完成一些与业务相关的定制化功能还是有困难的。比如对列表、文档库的添加、删除、修改的同时还要进行其他业务逻辑的处理。

由于WSS 3.0的对象模型非常庞大,不能一一介绍。微软提供了两个SDK,里面有WSS所有对象的示例,推荐读者安装相关的SDK。

8.1  对象介绍

新建一个C#的Windows工程,命名为“WindowsWSS”。引用“Microsort SharePoint Services”对象。在代码中添加以下命名空间。

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.Administration;

以下的代码段均在这个工程内进行测试。

8.1.1  SPWebApplication

当创建了一个Web应用程序后,就能够通过SPWebApplication来获取相关信息。Web应用程序包含网站集,是网站集的容器。

以下的代码可以返回当前系统下所有Web应用程序的集合。

请在窗体上添加一个按钮、一个listbox控件、一个文本控件(设置为多行),按照默认命名即可,代码如下所示:

private void button1_Click(object sender, EventArgs e)

{

    SPWebApplicationCollection webs=SPWebService.ContentService.WebApplications;

    foreach (SPWebApplication web in webs)

    {

        listBox1.Items.Add(web.DisplayName);

    }

}

运行后会打印出当前所有网站应用程序,如SharePoint –9000。

8.1.2  SPSite和SPWeb

SPSite是Web应用程序下的网站集。SPSite的RootWeb代表网站集的顶级网站(首要网站)。

SPWeb代表网站集下面的每个站点和子站点。访问站点的任何内容都需要从SPWeb 对象开始。从上面两者的关系可以看出来,网站集SPSite是SPWeb的集合。

可以使用以下方式来获取网站:

Ø    先得到SPSite。

SPSite site=new SPSite(“http://yang:9000”);

Ø    使用AllWebs方法得到当前网站集下面的知识库子站点kb。

SPWeb web1=site.AllWebs["kb"];

MessageBox.Show(web1.Title);

Ø    使用OpenWeb方法得到当前网站集下面的知识库子站点kb。

SPWeb web2 = site.OpenWeb("kb");

MessageBox.Show(web2.Title);

Ø    注意的是OpenWeb方法中的参数是一个相对的地址。

当在SharePoint环境中开发程序的时候,可以使用Http当前上下文Context来取得当前URL所对应的站点。

Ø    利用SPControl控件的上下文。

SPWeb web = SPControl.GetContextWeb(Context);

Ø    利用WSS对象的上下文SPContent。

SPWeb web = SPContext.Current.Web;

顶级网站(首要网站)访问子网站的列表

以下代码段展示了顶级网站(首要网站)访问子网站kb下的KB列表。

string listname = "KB";

SPWeb web = SPControl.GetContextWeb(Context).Webs["kb"];

SPList treeList = web.Lists[listname];

子网站访问顶级网站(首要网站)的列表

以下代码段展示了在子网站访问根网站(首要网站)下的tree分类列表。

string sourceTreeList = "tree";

SPWeb rootweb = SPControl.GetContextSite(Context).RootWeb;

SPList treeList = rootweb.Lists[sourceTreeList];

8.1.3  列表对象

8-1列表开发的一些对象模型如表8-1所示。

表8-1  列表开发的对象模型

   

   

SPList

列表对象

续表 

   

   

SPListCollection

列表集合。SPWeb.Lists返回网站所有列表的集合

SPListItem

列表的项

SPListItemCollection

列表项的集合。SPList.Items返回列表的所有列表项

SPViewCollection

视图集合对象

SPViewFieldCollection

视图字段集合

SPView

视图对象

SPDocumentLibrary

特殊的列表-文档库对象

SPField

列表字段

SPFieldCollection

列表字段集合

其他更多的模型对象请参考SDK。

1.获取列表Case

SPWeb web = SPControl.GetContextWeb(Context);

SPList list = web.Lists["Case"];

2.添加列表

SPWeb web = SPControl.GetContextWeb(Context);

SPList list = web.Lists["Case"];

SPListItemCollection lists = list.Items;

SPListItem listItem = list.Items.Add();

listItem["标题"] = this.TextBoxTitel.Text;

listItem["详细内容"] = this.TextBoxContent.Text;

listItem["联系电话"] = this.TextBoxTel.Text;

listItem["电子邮件"] = this.TextBoxEmail.Text;

listItem["紧急程度"] = this.DropDownListPRI.SelectedItem.Text;

listItem["分类"] = getTyepName();

listItem.Update();

3.得到列表项

SPWeb web =SPControl.GetContextWeb(Context);

SPList list=web.Lists["case"];

//得到列表项的ID

Int  ID=1;

SPListItem listItem = list.Items.GetItemById(ID);

if (listItem["分类"] != null)

{

    this.Label1.Text = listItem["分类"].ToString();

}

4.列表循环输出

SPSite site = new SPSite("http://yang:9000");

SPWeb spweb = site.OpenWeb();

SPList list = spweb.Lists["case"];

SPListItemCollection listitems = list.Items;

 foreach (SPListItem listitem in listitems)

 {

    this.textBox1.Text += listitem["标题"].ToString () + Environment.NewLine;

 }

这段代码的运行结果将列表Case里的标题列内容全部输出。

5.删除列表

SPSite site = new SPSite("http://yang:9000");

SPWeb web = site.OpenWeb();

SPListCollection lists = web.Lists;

//删除Case列表

SPList list = lists["case"];

System.Guid listGuid = list.ID;

lists.Delete(listGuid);

6.操作视图

 SPSite site = new SPSite("http://yang:9000");

 SPWeb spweb = site.OpenWeb();

 SPList list = spweb.Lists["case"];

 //case列表下的所有视图

 SPViewCollection listitems = list.Views;

 MessageBox.Show(listitems.Count.ToString ());

 //列出标题

 foreach (SPView oViewSrc in listitems)

   {

     this.textBox1.Text += oViewSrc.Title + Environment.NewLine;

   }

 //得到单个视图的信息

 Guid viewguid=list.Views["我的日常工作"].ID;

 SPView sv=list.GetView(viewguid);

 SPListItemCollection collItemsSrc= list.GetItems(sv);

 SPViewFieldCollection collViewFields = sv.ViewFields;

 foreach (SPListItem oItemSrc in collItemsSrc)

 {

      for (int intIndex = 0; intIndex < collViewFields.Count; intIndex++)

           {

         this.textBox1.Text +=collViewFields[intIndex].ToString () + " :: " + oItemSrc[collViewFields[intIndex]].ToString() + Environment.NewLine; ;

           }

}

运行结果如图8-2所示。

图8-2 视图信息

7.列表到DataTable

对列表的循环访问,不仅代码多,而且容易出错,一般处理的办法是把一个列表转成DataTable来操作,相信读者对DataTable很熟悉,这样降低了代码的复杂度,简化了开发过程。

Ø    使用SPListItemCollection列表项的集合对象的GetDataTable方法

private DataTable GetData()

{

    string sourceTreeList = "tree";

    SPWeb rootweb = SPControl.GetContextSite(Context).RootWeb;

    SPList treeList = rootweb.Lists[sourceTreeList];

    SPListItemCollection Items = treeList.Items;

    return Items.GetDataTable();

}

Ø    自定义实现列表对象转化为DataTable

Ø    定义一个字段列表

string[] pSourceSPListFields ={ "ClassID", "ClassName", "ParentID" };

Ø    构造内容

private DataTable _sourceDataTable;

private DataTable ListToDataTable()

{

    //构造表头

    this._sourceDataTable = this.ColumnNameDataTable();

    SPWeb web =  SPControl.GetContextWeb(Context);

    SPList treeList = web.Lists[sourceTreeList];

    DataTable dt = new DataTable();

    SPListItemCollection caseItems = treeList.Items;

    foreach (SPListItem caseItem in caseItems)

    {

        try

        {

            DataRow rowNew = _sourceDataTable.NewRow();

            for (int intI = 0; intI < this.pSourceSPListFields.Length; intI++)

            {

                if (caseItem[pSourceSPListFields[intI]] != null)

                {

                    if (treeList.Fields[this.pSourceSPListFields[intI]]. FieldValueType.ToString() == "Microsoft.SharePoint.SPFieldUserValue")

                    {

                        string createrUserName = caseItem[this.pSourceSPList Fields[intI]].ToString();

                        int index = createrUserName.IndexOf(';');

                        int createrUserID = Convert.ToInt32(createrUserName. Substring(0, index));

                        SPUser createrUser = web.AllUsers.GetByID(creater UserID);

                        rowNew[pSourceSPListFields[intI]] = createrUser.Name;

                    }

                    else

                    {

                        Object columnType = _sourceDataTable.Columns [this.pSourceSPListFields[intI]].DataType;

                        rowNew[pSourceSPListFields[intI]] = caseItem[pSource SPListFields[intI]];

                    }

                }

            }

            _sourceDataTable.Rows.Add(rowNew);

        }

        catch

        {

        }

    }

    return this._sourceDataTable;

}

Ø    构造表头

public DataTable ColumnNameDataTable()

{

    SPWeb web = SPControl.GetContextWeb(Context);

    SPList treeList = web.Lists[sourceTreeList];

    DataTable dt = new DataTable();

    SPListItemCollection caseItems = treeList.Items;

    for (int intI = 0; intI < pSourceSPListFields.Length; intI++)

    {

        DataColumn columnNew = new DataColumn();

        columnNew.ColumnName = pSourceSPListFields[intI];

        dt.Columns.Add(columnNew);

    }

    return dt;

}

Ø    调用过程

private DataTable GetData()

        {

            Return ListToDataTable();

        }

在案例中,这两种方式使用得都非常频繁,为了减少代码量,后面章节代码中只会写方法名而忽略具体过程实现。

8.1.4  操作文档库

文档库具有列表的所有属性,但是作为文档库又具有文件格式的所有属性。列表中每个项目可以使用SPListItem对象来操作。文档库中的项目则可以使用SPFile对象来操作。

通过以下代码来学习文件对象。

SPSite site = new SPSite("http://yang:9000/kb");

SPWeb spweb = site.OpenWeb();

SPFolder myFolder = spweb.GetFolder("kb");

SPFileCollection myFiles = myFolder.Files;

FileStream fStream = File.OpenRead(@"c:\aaa.txt");

byte[] contents = new byte[fStream.Length];

fStream.Read(contents, 0, (int)fStream.Length);

fStream.Close();

 string path = site.Url + "/kb/KB/";

 string filename=DateTime.Now.ToString().Replace(" ","").Replace(":","")+".txt";

 SPFile file = myFiles.Add(path+filename,contents);

 file.Item["知识库标题"] = "测试知识库";

 file.Item["内容"] = "计算机的管理是一个非常复杂的工作";

 file.Item["分类"] = "4";

 file.Item.Update();

使用SPFolder myFolder = spweb.GetFolder("kb")代码段来得到文档库KB的文件夹。

之后使用SPFileCollection myFiles = myFolder.Files来得到文件集合。然后使用myFiles.Add对象来添加一个文本文件,这里可以为任意文件。最后通过file对象的item来赋值并完成更新操作。

最终界面如图8-3所示。

7

图8-3  添加记录后的文档库

当然,还可以用操作列表的方法来操作文档库。通过file对象能够获取文件的版本、大小等信息。在此不再阐述,请参考WSS SDK。

8.1.5  操作用户和用户组

8-2用户和用户组的对象模型如表8-2所示。

表8-2  用户和用户组的对象模型

   

   

SPUser

用户对象、域用户或者表单验证用户

SPUserCollection

用户对象的集合

SPGroup

用户组

SPGroupCollection

用户组的集合

1.得到站点下所有的用户

SPSite site = new SPSite("http://yang:9000");

SPWeb web= site.OpenWeb();

  foreach (SPUser user in web.SiteUsers)

   {

       this.textBox1.Text+=user.Name+Environment.NewLine;

   }

输入结果:

CaoJing

DuanFuFeng

GanShiQiang

NT AUTHORITY\authenticated users

NT AUTHORITY\local service

YangYongGang

ZhongDeRong

系统账户

2.得到站点下所有的用户组

SPSite site = new SPSite("http://yang:9000");

SPWeb web = site.OpenWeb();

foreach (SPGroup group in web.Groups)

{

    this.textBox1.Text += group.Name +Environment.NewLine;

}

输出结果:

helpdesk

manager

support

test成员

test访问者

test所有者

层次结构管理者

查看者

快速部署用户

设计者

审批者

受限制读者

样式资源读者

8.1.6  查询

通过SPQuery类来完成对列表的查询操作。

使用SPQuery需要设置如表8-3所示的几个属性

表8-3  SPQuery类的属性说明

   

   

ViewFields

查询结果中要显示的字段。这个属性的设置如:<FieldRef Name=”Title” />

Query

查询条件包括分组与排序条件

RowLimit

返回结果的行数

其中查询条件的设置需要满足CAML(协作应用程序标记语言)的语法标准。关于CAML具体的语法在这里不作具体介绍。这里仅介绍CAML语言的操作符,如表8-4所示。

表8-4  CAML语言的操作符说明

  

   

Geq

>=

EQ

=

Gt

Lt

Neq

!=

Contains

包含

使用CAML查询有一点需要清楚,在CAML语法中使用的字段名并不是创建的字段名,而是MOSS系统内部的名称InternalName,先看以下代码。

SPSite site = new SPSite("http://yang:9000");

SPWeb spweb = site.OpenWeb();

SPList list = spweb.Lists["case"];

SPListItemCollection myItems = list.Items;

 SPListItem item = myItems[0];

 for (int i = 0; i < item.Fields.Count; i++)

    {

      this.textBox1.Text += item.Fields[i].Title + ":" + item.Fields[i].InternalName + Environment.NewLine;

    }

运行后结果如下所示:

内容类型 ID:ContentTypeId

标题:Title

审批者注释:_ModerationComments

文件类型:File_x0020_Type

维护人员:_x7ef4__x62a4__x4eba__x5458_

故障大类:_x6545__x969c__x5927__x7c7b_

故障小类:_x6545__x969c__x5c0f__x7c7b_

状态:_x72b6__x6001_

用户处室名称:_x7528__x6237__x5904__x5ba4__x54

用户姓名:_x7528__x6237__x59d3__x540d_

用户电话:_x7528__x6237__x7535__x8bdd_

电子邮件:_x7535__x5b50__x90ae__x4ef6_

故障情况说明:_x6545__x969c__x60c5__x51b5__x8b

派工时间:_x6d3e__x5de5__x65f6__x95f4_

紧急程度:_x7d27__x6025__x7a0b__x5ea6_

实际故障情况说明:_x5b9e__x9645__x6545__x969c__x60

解决方案:_x89e3__x51b3__x65b9__x6848_

处理时长:_x5904__x7406__x65f6__x957f_

解决问题时间:_x89e3__x51b3__x95ee__x9898__x65

问题解决方式:_x95ee__x9898__x89e3__x51b3__x65

是否加入知识库:_x662f__x5426__x52a0__x5165__x77

已打分:_x5df2__x6253__x5206_

分类:_x5206__x7c7b_

rr:rr

case发送邮件:case_x53d1__x9001__x90ae__x4ef6_

正文:Body

到期日期:Expires

Meeting Room#:Meeting_x0020_Room_x0023_

内容类型:ContentType

ID:ID

修改时间:Modified

创建时间:Created

创建者:Author

修改者:Editor

通过这个运行结果,看到前面的正是MOSS中创建的字段,而冒号之后的则是系统内部处理的名称。如果把一个栏删除,再添加同样的栏,相应的InternalName会发生变化,需要重新获取。

接下来进行CAML的查询,从列表Case的标题中找到包含“计算机”的记录,并且显示5条。

在界面上增加了一个dataGridView表格控件。代码如下所示:

SPSite site = new SPSite("http://yang:9000");

SPWeb spweb = site.OpenWeb();

SPList list = spweb.Lists["case"];

SPQuery query = new SPQuery();

query.ViewFields = "<FieldRef Name='Title'/>

<FieldRef Name='_x95ee__x9898__x89e3__x51b3__x65'/><FieldRef Name='Created'/>";

query.Query = "<Where><Contains><FieldRef Name='Title'/><Value Type='Text'>计算机</Value></Contains></Where>";

query.RowLimit = 5;

SPListItemCollection myItems = list.GetItems(query);

this.dataGridView1.DataSource = myItems.GetDataTable();

运行结果如图8-4所示。

23

图8-4  绑定后的数据表格控件

注意这个表格显示了标题、故障情况说明和创建时间。其中_x6545__x969c__x60c5__ x51b5__x8b是故障情况说明字段的InternalName。如果把代码中<FieldRef Name='Title'/>改成<FieldRef Name='标题'/>,即

query.Query = "<Where><Contains><FieldRef Name='标题'/><Value Type='Text'>计算机</Value></Contains></Where>";

则系统会报告一个错误。错误如下:

一个或多个域类型未正确安装。请转到列表设置页删除这些域。

posted on 2010-01-25 13:22  地下室的流星雨  阅读(598)  评论(0编辑  收藏  举报