标签:des style blog http color io os 使用 ar
SharePoint 2013开发入门探索(二)- 列表操作 我们如何用代码对SharePoint列表做些例如增删改查的操作呢?如果您的程序可以部署到服务器上,就可以使用 服务器对象模型,因为服务器对象模型提供的功能最多,限制最少;否则可能要选择客户对象模型等其他方式,这可能会遇到一些功能限制;另外还有一些其他的访问方式,例如Web服务等。如何在 SharePoint 2013 中选择正确的 API 集请参考链接http://msdn.microsoft.com/zh-cn/library/jj164060.aspx 。 我们首先研究下服务器对象模型。使用服务器对象模型需要到服务器端部署,所以没有服务器部署权限的话就不能使用了。使用服务对象模型要引用程序集Microsoft.SharePoint —— 如果您创建的是SharePoint项目,这个引用默认就会有的。 在服务器对象模型中我经常使用的几个.NET类是SPSite、SPWeb、SPList还有SPListItem,下面简单介绍下这几个类。 网站集 (由一个首要网站以及该网站下的所有网站组成,参考:http://technet.microsoft.com/zh-cn/library/cc262410.aspx )对应的类是SPSite,可以传参网站集URL给SPSite的构造方法创建对象。一般您可以这样用。 using (SPSite spSite = new SPSite("http://SharePointServer/"))
{
//TODO......
}
有时候你可能要提升一下权限以场管理员身份执行,则可以用下面的写法——这是服务器对象模型的优势,但是如果项目选择为“部署为沙盒解决方案”则不能提升到场管理员权限。 SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite spSite = new SPSite("http://SharePointServer/"))
{
//TODO......
}
});
SharePoint里的 用户 对应的是SPUser类,也可以使用SPUserToken构造网站集对象实现模拟用户身份执行代码。 SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite spSite = new SPSite("http://SharePointServer/"))
{
SPUser imitatedUser = spSite.RootWeb.EnsureUser(@"contoso\sanzhang");
SPUserToken token = imitatedUser.UserToken;
using (SPSite siteWithUser = new SPSite("SharePointServerUrl", token))
{
//TODO......
}
}
});
网站 对应的类是SPWeb,SPSite有一个RootWeb属性,是网站集的根网站;SPSite还有个AllWebs属性,是它的所有网站集合(可以用索引访问),要得到SPWeb对象还可以调用SPSite对象的OpenWeb方法,传给一个URL参数(根网站的URL和网站集是相同的,所以下面的代码传空字符串,其他子网站要传标识网站的URL部分)。每个SPWeb对象也有个Webs属性,是这个网站的子网站(也可以用索引访问)。 using (SPSite spSite = new SPSite("http://SharePointServer/"))
{
//获取网站集根网站对象
SPWeb spRootWeb = spSite.RootWeb;
Console.WriteLine("网站集的根网站是{0}", spRootWeb.Title);
//用网站ID获取子网站对象
Guid webId = new Guid("{4a106421-ae78-40fd-ad62-77fecb67cf27}");
SPWeb spWeb = spSite.AllWebs[webId];
Console.WriteLine("该网站是{0}", spWeb.Title);
spWeb = spRootWeb.Webs[webId];
Console.WriteLine("该网站是{0}", spWeb.Title);
//用网站名称获取子网站对象
string name = "mysubweb1";
spWeb = spSite.AllWebs[name];
Console.WriteLine("该网站是{0}", spWeb.Title);
spWeb = spRootWeb.Webs[name];
Console.WriteLine("该网站是{0}", spWeb.Title);
//用网站URL获取子网站对象
string url = @"/mysubweb1";
spWeb = spSite.OpenWeb(url);
Console.WriteLine("该网站是{0}", spWeb.Title);
}
获取对网站和其他关键对象的引用请参考:http://msdn.microsoft.com/zh-cn/library/ms468609(v=office.14).aspx 。 列表 对应的类是SPList,其实SPList类对应的不仅仅是狭义的自定义列表,文档库、图片库、日历、通知、任务都可以用它来操作,还有网站资产、用户信息列表、解决方案库、列表模版库、Web部件库等等。SPWeb对象有个Lists属性,是SPListCollection类型,遍历它或者用ID、Title做索引可得到SPList对象。想了解网站中有哪些List可以用下面的代码查看: //获取网站所有列表
foreach (SPList list in spWeb.Lists)
{
Console.WriteLine("Title:{0} BaseType:{1} BaseTemplate:{2}", list.Title, list.BaseType, list.BaseTemplate);
}
//用列表标题获取列表对象
string title = @"我的客户列表";
SPList spList = spWeb.Lists[title];
Console.WriteLine("该列表是{0}。", spList.Title);
//用列表ID获取列表对象
Guid id = new Guid(@"{3824b091-c7b8-409c-bcc0-7cce487d6b49}");
spList = spWeb.Lists[id];
Console.WriteLine("该列表是{0}。", spList.Title);
//用列表URL获取列表对象
string listUrl = string.Format(@"{0}/{1}", spWeb.Url, "Lists/MyCustomerList/AllItems.aspx");
spList = spWeb.GetList(listUrl);
Console.WriteLine("该列表是{0}。", spList.Title);
您还是否记得这些列表属性,我们在开发自定义列表时都设置过? 列表项 对应的类是SPListItem,SPList对象的Items属性是它的项目的集合,是SPListItemCollection类型的,枚举它的元素就是SPListItem对象了。不过您想访问列表项的时候一般不要直接通过SPList对象的Items属性,特别是已经存储了很多项目的大数据列表,因为可能会有不必要的数据加载影响性能。例如您想知道列表中已存在多少个项目,可以直接访问SPList对象的ItemCount属性,而不是SPList对象的Items属性的Count;如果您想得到列表中的某个项目可以调用SPList对象的GetItemById、GetItemByUniqueId等方法。 //用列表标题获取列表对象
SPList spList = spWeb.Lists["我的客户列表"];
//获取用户信息列表的项目数量
int userCount = spList.ItemCount;
Console.WriteLine("我的客户列表共有{0}条项目。", userCount.ToString());
//用项目ID获取项目对象
int itemId = 18;
SPListItem spListItem = spList.GetItemById(itemId);
Console.WriteLine("该客户是{0}。", spListItem.Title);
//用项目UniqueID获取项目对象
Guid itemUniqueId = new Guid("{83815a27-6291-416d-8db6-a77bcae4bb86}");
spListItem = spList.GetItemByUniqueId(itemUniqueId);
Console.WriteLine("该客户是{0}。", spListItem.Title);
列表对象还有一个Fields的属性,是SPFieldCollection类型,遍历这个字段集合可以得到SPField对象。这就是列表的字段信息,包括字段内部名称、显示名称、类型等等。我们要访问列表项目的某个属性时就可以用SPField对象的ID,InternalName或Title。 string title = @"我的客户列表";
SPList spList = spWeb.Lists[title];
SPFieldCollection spFields = spList.Fields;
//获取列表的字段信息
foreach (SPField field in spFields)
{
Console.WriteLine("Title:{0} InternalName:{1} TypeDisplayName:{2} TypeAsString:{3}", field.Title, field.InternalName, field.TypeDisplayName, field.TypeAsString);
}
Guid fieldId = new Guid("{a943ca8c-a2ad-4a90-8a78-2f6a202f6553}");
SPField spField = spFields[fieldId];
SPListItem spListItem = spList.Items[0];
//用字段的ID访问列表项目属性
Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.Id].ToString());
//用字段的InternalName访问列表项目属性
Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.InternalName].ToString());
Console.WriteLine("该用户的消费金额是{0}。", spListItem.GetFormattedValue(spField.InternalName));
//用字段的Title访问列表项目属性
Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.Title].ToString());
Console.WriteLine("该用户的消费金额是{0}。", spListItem.GetFormattedValue(spField.Title));
您还记得开发自定义列表栏的时候我们一起设置的那些字段属性吗? SPList对象还有个GetItemByIdAllFields方法和GetItemByIdSelectedFields方法。看来我们可以按需索取项目字段了。 //用列表标题获取列表对象
string title = @"我的客户列表";
SPList spList = spWeb.Lists[title];
int itemId = 1;
SPListItem spListItem = spList.GetItemByIdSelectedFields(itemId, new[] { "CustomerName", "Recency", "Frequency", "Monetary" });
//用项目的ID和字段的InternalName访问列表项目
Console.WriteLine("客户{0}的最近消费时间是{1}消费频率是{2}消费金额是{3}。", spListItem["CustomerName"].ToString(), spListItem["Recency"].ToString(), spListItem["Frequency"].ToString(), spListItem["Monetary"].ToString());
不过,我把GetItemByIdSelectedFields方法的数组参数减掉了两个项"Frequency"和"Monetary"再运行,竟然没有看到我期待的、闪电般美丽的异常!不是说只要两个字段吗?而且随后我把SPListItem对象的Xml属性也输出时有看到了好多不是我指定索取的字段信息! string title = @"我的客户列表";
SPList spList = spWeb.Lists[title];
int itemId = 1;
//删掉"Frequency"、 "Monetary"
SPListItem spListItem = spList.GetItemByIdSelectedFields(itemId, new[] { "CustomerName", "Recency"});
//用项目的ID和字段的InternalName访问列表项目
Console.WriteLine("客户{0}的最近消费时间是{1}消费频率是{2}消费金额是{3}。", spListItem["CustomerName"].ToString(), spListItem["Recency"].ToString(), spListItem["Frequency"].ToString(), spListItem["Monetary"].ToString());
Console.WriteLine(@"XML:{0}",spListItem.Xml);
查看一下GetItemByIdSelectedFields方法的源代码,发现在拼接CAML查询字段时有个对SPField对象MustFetchByDefault的判断,如果这个属性是True,没有指定也会查询,而且这个SPField对象MustFetchByDefault属性是internal的。 public SPListItem GetItemByIdSelectedFields(int id, params string[] fields)
{
if (fields == null)
{
throw new ArgumentNullException("fields");
}
StringBuilder builder = new StringBuilder();
foreach (string str in fields)
{
if (str != null)
{
builder.Append("<FieldRef Name=\"" + str + "\"/>");
}
}
foreach (SPField field in this.Fields)
{
bool flag = false;
foreach (string str2 in fields)
{
if (str2 == field.InternalName)
{
flag = true;
break;
}
}
if (!flag && field.MustFetchByDefault)
{
builder.Append("<FieldRef Name=\"");
builder.Append(field.InternalName);
builder.Append("\"/>");
}
}
return this.GetItemById(id, null, false, builder.ToString());
}
如何读取列表项中字段的值请参考: http://msdn.microsoft.com/zh-cn/library/ff521580(v=office.14).aspx 。 在读取项目属性时,有些类型是比较特殊的:例如多个用户或用户组,它可以转为SPFieldUserValueCollection类型,这是个SPFieldUserValue对象的集合; 用户或用户组 、超链接或图片这样的字段取出来时String类型,您要解析可以用字符串截取方式,也可以对应构造成SPFieldUserValue、SPFieldUrlValue对象,直接访问它们的属性。 SPListItem spListItem = spList.GetItemById(itemId);
//直接ToString,用户是[ID]+[;#] + [显示名];链接是[URL] + [,] + [显示文本]
Console.WriteLine("客户的分享者是{0} 所有者是{1} 业务系统链接是{2}。", spListItem["Sharers"], spListItem["Owner"].ToString(), spListItem["BusinessPage"].ToString());
//截取字符串取属性
Console.WriteLine("客户的所有者的显示名是{0} 业务系统链接的URL是{1}。", spListItem["Owner"].ToString().Split(new[] { @";#" }, StringSplitOptions.None)[1], spListItem["BusinessPage"].ToString().Split(‘,‘)[0]);
//转为相应对象取属性
SPFieldUserValueCollection shares = (SPFieldUserValueCollection)spListItem["Sharers"];
foreach (SPFieldUserValue share in shares)
{
if (share.User != null)
{
SPUser user = share.User;
Console.WriteLine(@"找到个用户{0}", user.Name);
}
else
{
SPGroup spGroup = spWeb.Groups.GetByID(share.LookupId);
Console.WriteLine(@"找到个用户组{0}", spGroup.Name);
}
}
SPFieldUserValue owner = new SPFieldUserValue(spWeb, spListItem["Owner"].ToString());
SPFieldUrlValue businessPage = |