步步为营 SharePoint 开发学习笔记系列 九、SharePoint web service 开发(上)
概要
Sharepoint中提供了很多开箱即用的Web Service,使用这些web service我们可以进行远程调用, 在"web server extensions\12\ISAPI"(其通常位于C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI")之下的"Microsoft Shared"目录中有大部分Web Services的物理文件。用于管理中心工具的管理Web Service位于ADMISAPI文件夹中,其在管理中心控制台里是一个名为"_vti_adm"的虚拟目录。当你创建了一个SharePoint站点时,它将包含一个名为"_vti_bin"的虚拟目录,以指向这个位置。IIS不为子站点包含任何应用程序或虚拟目录,它们只是包含通过 SharePoint元数据和HttpModules实现的对_vti_bin虚拟目录的映射。
先看下Lists.asmx中的一些常用功能
首先我们先连接web Service
public static NetworkCredential GetCredentials(SiteType type) { return new System.Net.NetworkCredential(ConfigurationManager.AppSettings["Source_SPWSUserName"], ConfigurationManager.AppSettings["Source_SPWSUserPassword"], ConfigurationManager.AppSettings["Source_SPWSDomain"]); } /// <summary> /// Get the list webservice based on the url /// </summary> /// <returns></returns> public static SPListWS.Lists GetListWebService(ListBE listProperty) { string wsUrl = GetWSUrl(listProperty) + "_vti_bin/Lists.asmx"; SPListWS.Lists ws = new SPListWS.Lists(); ws.Url = wsUrl; ws.Credentials = WSHelper.GetCredentials(listProperty.Type); return ws; }
再把web service引用进来
Lists.GetListItems的用法
根据条件来查询的query语句
private string GetCondition { get { return @"<Where> <And> <And> <Geq> <FieldRef Name='Created' /> <Value Type='DateTime'>{0}</Value> </Geq> <Leq> <FieldRef Name='Created' /> <Value Type='DateTime'>{1}</Value> </Leq> </And> <Gt> <FieldRef Name='ID' /> <Value Type='Counter'>0</Value> </Gt> </And> </Where>"; } }
而后再调用Lists.GetListItems方法,返回的是XmlNode的结果集
/// <summary> /// /// </summary> /// <returns></returns> private List<ListItemBE> GetSourceListItems(DateTime startDate, DateTime endDate) { int rowLimit = 8000; XmlDocument xmlDoc = new System.Xml.XmlDocument(); XmlElement query = xmlDoc.CreateElement("Query"); XmlElement viewFields = xmlDoc.CreateElement("ViewFields"); XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions"); /*Use CAML query*/ query.InnerXml = string.Format(GetCondition, SPUtility.CreateISO8601DateTimeFromSystemDateTime(startDate), SPUtility.CreateISO8601DateTimeFromSystemDateTime(endDate)); viewFields.InnerXml = GetColumnFieldRef(MigrateProperty.AllColumn); queryOptions.InnerXml = "<ViewAttributes Scope=\"RecursiveAll\" />"; MigrateProperty.AllColumn.Remove("ID"); System.Xml.XmlNode nodes = _ws.GetListItems(_listProperty.ListName, string.Empty, query, viewFields, rowLimit.ToString(), queryOptions, null); return GetListItemListFromXml(nodes); }
从XmlNode取得我们需要的数据
/// <summary> /// /// </summary> /// <param name="nodes"></param> /// <returns></returns> private List<ListItemBE> GetListItemListFromXml(XmlNode nodes) { UserOperations userOperations = new UserOperations(_listProperty); List<ListItemBE> result = new List<ListItemBE>(); ListItemBE listItem; foreach (XmlNode node in nodes) { if (node.Name == "rs:data") { for (int i = 0; i < node.ChildNodes.Count; i++) { if (node.ChildNodes[i].Name == "z:row") { listItem = GetListItemBEFromXmlNode(node.ChildNodes[i], userOperations); if (node.ChildNodes[i].Attributes.GetNamedItem("ows_ParentFolderId") == null) { listItem.ColumnValue.Add("FSObjType", "1"); listItem.ColumnValue.Add("BaseName", listItem.ColumnValue["Title"]); result.Add(listItem); } else { listItem.ColumnValue.Add("FileRef", node.ChildNodes[i].Attributes["ows_FileRef"].Value); secondListItem.Add(listItem); } } } } } return result; } /// <summary> /// /// </summary> /// <param name="node"></param> /// <param name="userOperations"></param> /// <returns></returns> private ListItemBE GetListItemBEFromXmlNode(XmlNode node, UserOperations userOperations) { ListItemBE listItem = new ListItemBE(); listItem.Id = node.Attributes["ows_ID"].Value; foreach (KeyValuePair<string, string> column in MigrateProperty.AllColumn) { string nodeValue = string.Empty; if (node.Attributes.GetNamedItem("ows_" + column.Key) != null) nodeValue = node.Attributes["ows_" + column.Key].Value; if (string.Equals(column.Key, "Attachments", StringComparison.InvariantCultureIgnoreCase)) { GetAttachmentFromNode(nodeValue, listItem.Id); continue; } if (string.Equals(column.Key, "Author", StringComparison.InvariantCultureIgnoreCase) || string.Equals(column.Key, "Editor", StringComparison.InvariantCultureIgnoreCase)) { listItem.ColumnValue.Add(column.Value, userOperations.GetUserNameByOriginalName(nodeValue)); continue; } if (node.Attributes.GetNamedItem("ows_" + column.Key) != null) listItem.ColumnValue.Add(column.Value, nodeValue); else listItem.ColumnValue.Add(column.Value, string.Empty); } return listItem; }
MigrateProperty.AllColumn定义如下
public Dictionary<string,string> AllColumn { get { Dictionary<string,string> listColumn = new Dictionary<string,string>(); listColumn.Add("ID", "ID"); listColumn.Add("Title", "Title"); listColumn.Add("Author", "Author"); listColumn.Add("Created", "Created"); listColumn.Add("Editor", "Editor"); listColumn.Add("Modified", "Modified"); listColumn.Add("Attachments", "Attachments"); listColumn.Add("ContentType", "ContentType"); listColumn.Add("Body", "Body"); listColumn.Add("ThreadIndex", "ThreadIndex"); listColumn.Add("ParentFolderId", "ParentFolderId"); listColumn.Add("TrimmedBody", "TrimmedBody"); return listColumn; } }
而我们ListItemBE的定义如下,保存返回的结果集
public class ListItemBE { public ListItemBE() { ColumnValue = new Dictionary<string, string>(); } public string Id { get; set; } public Dictionary<string, string> ColumnValue { get; set; } }
如上所示的步骤,我们就可以根据自定义的query语句通过web service来取得结果集。
Lists.UpdateListItems的用法
首先看下Insert item的xml格式
<Batch OnError="Continue" ListVersion="1" ViewName="270C0508-A54F-4387-8AD0-49686D685EB2"> <Method ID="1" Cmd="New"> <Field Name='ID'>New</Field> <Field Name="Title">Value</Field> <Field Name="Date_Column">2007-3-25</Field> <Field Name="Date_Time_Column"> 2006-1-11T09:15:30Z</Field> </Method> </Batch>
如果插入的item是folder时,插入的xml格式如下
<Batch OnError="Continue" PreCalc="TRUE" ListVersion="0" ViewName="{EF2F5A21-0FD0-4654-84ED-112B4F5A48F8}"> <Method ID="1" Cmd="New"> <Field Name="ID">New</Field> <Field Name="FSObjType">1</Field> <Field Name="BaseName">Name</Field> </Method> </Batch>
我们生成xml时做如下处理,根据我们定义的ListItemBE方法来做如下处理
/// <summary> /// Returns the XML that will be used to batch insert items /// </summary> /// <param name="batch"></param> /// <returns></returns> private string GetInsertXML(List<ListItemBE> batch) { StringBuilder xml = new StringBuilder(); xml.Append(string.Format(@"<Batch OnError=""Continue"" {0}>", _listProperty.RootUrl)); foreach (ListItemBE listItem in batch) { xml.AppendFormat(@"<Method ID=""{0}"" Cmd=""New"">", listItem.Id); xml.Append(GetInsertInnerXml(listItem)); xml.Append("</Method>"); } xml.Append("</Batch>"); return xml.ToString(); }
调用方式如下:
/// <summary> /// Insert the items /// </summary> /// <param name="batch"></param> /// <returns></returns> private UpdateResultBE InsertItems(List<ListItemBE> batch) { //Get the Insert XML Node XmlNode batchNode = GetInsertXmlNode(batch); XmlNode result = null; _logger.Log("Started batch uploading list Items"); try { //Call the webservice result = _ws.UpdateListItems(_listProperty.ListName, batchNode); } catch (Exception ex) { _logger.Log(String.Format("Error Inserting Items. Exception: {0}. Stack Trace: {1}", ex.Message, ex.StackTrace)); } _logger.Log("Finished batch uploading list items"); //Transform the result into an object UpdateResultBE insertResult = new UpdateResultBE(result, _listProperty); LogInsertResult(insertResult); return insertResult; }
我们的UpdateResultBE定义如下,它是用来获取返回我们想要的结果集。
返回结果集格式如下:
* <Results xmlns="http://schemas.microsoft.com/sharepoint/soap/"> <Result ID="1,Update"> <ErrorCode>0x00000000</ErrorCode> <z:row ows_ID="4" ows_Title="Title" ows_Modified="2003-06-19 20:31:21" ows_Created="2003-06-18 10:15:58" ows_Author="3;#User1_Display_Name" ows_Editor="7;#User2_Display_Name" ows_owshiddenversion="3" ows_Attachments="-1" ows__ModerationStatus="0" ows_LinkTitleNoMenu="Title" ows_LinkTitle="Title" ows_SelectTitle="4" ows_Order="400.000000000000" ows_GUID="{4962F024-BBA5-4A0B-9EC1-641B731ABFED}" ows_DateColumn="2003-09-04 00:00:00" ows_NumberColumn="791.00000000000000" xmlns:z="#RowsetSchema" /> </Result> <Result ID="2,Update"> <ErrorCode>0x00000000</ErrorCode> <z:row ows_ID="6" ows_Title="Title" ows_Modified="2003-06-19 20:31:22" ows_Created="2003-06-18 19:07:14" ows_Author="2;#User1_Display_Name" ows_Editor="6;#User2_Display_Name" ows_owshiddenversion="4" ows_Attachments="0" ows__ModerationStatus="0" ows_LinkTitleNoMenu="Title" ows_LinkTitle="Title" ows_SelectTitle="6" ows_Order="600.000000000000" ows_GUID="{2E8D2505-98FD-4E3E-BFDA-0C3DEBE483F7}" ows_DateColumn="2003-06-23 00:00:00" ows_NumberColumn="9001.00000000000000" xmlns:z="#RowsetSchema" /> </Result> ... </Results>
我们取结果的方式如下:
/// <summary> /// Class that holds the UpdateListItems webservice method result /// </summary> internal class UpdateResultBE { public List<SingleResultBE> Result { get; set; } /// <summary> /// Contructor that uses the result xml to load into objects /// </summary> /// <param name="resultXml"></param> public UpdateResultBE(XmlNode resultXml, ListBE properties) { Result = new List<SingleResultBE>(); SingleResultBE singleResult; if (resultXml == null) return; foreach (XmlNode node in resultXml.ChildNodes) { singleResult = new SingleResultBE(); try { singleResult.Id = node.Attributes["ID"].Value.Split(',')[0]; singleResult.Operation = node.Attributes["ID"].Value.Split(',')[1]; XmlNode errorCodeNode = FindChildNode(node, "ErrorCode"); if (errorCodeNode != null) { singleResult.ErrorCode = errorCodeNode.InnerText; } XmlNode errorTextNode = FindChildNode(node, "ErrorText"); if (errorTextNode != null) { singleResult.ErrorMessage = errorTextNode.InnerText; } XmlNode zRow = FindChildNode(node, "z:row"); if (zRow != null) { singleResult.Attachments = Convert.ToInt32(zRow.Attributes["ows_Attachments"].Value); singleResult.Created = DateTime.Parse(zRow.Attributes["ows_Created"].Value); singleResult.ListItemId = Convert.ToInt32(zRow.Attributes["ows_ID"].Value); singleResult.ModerationStatus = Convert.ToInt32(zRow.Attributes["ows__ModerationStatus"].Value); singleResult.Modified = DateTime.Parse(zRow.Attributes["ows_Modified"].Value); singleResult.ListItemGuid = zRow.Attributes["ows_UniqueId"].Value; if (zRow.Attributes.GetNamedItem("ows_Title") != null) singleResult.Title = zRow.Attributes["ows_Title"].Value; singleResult.BaseName = zRow.Attributes["ows_BaseName"].Value; singleResult.FileDirRef = zRow.Attributes["ows_FileDirRef"].Value; singleResult.FileRef = zRow.Attributes["ows_FileRef"].Value; if (zRow.Attributes.GetNamedItem("ows_BaseName") != null) singleResult.BaseName = zRow.Attributes["ows_BaseName"].Value; } Result.Add(singleResult); } catch (Exception ex) { Logger.Logger logger = Logger.LoggerFactory.GetLogger(); logger.Log(String.Format("Error when parsing the result. Exception: {0} \n XML: {1}", ex.Message, node.InnerXml)); } } } /// <summary> /// Find the Child node specified by name /// </summary> /// <param name="parent">Parent Node</param> /// <param name="childNodeName">Child node name</param> /// <returns></returns> private XmlNode FindChildNode(XmlNode parent, string childNodeName) { foreach (XmlNode node in parent.ChildNodes) { if (node.Name == childNodeName) return node; } return null; } }
SingleResultBE就是我们想要的结果集.
/// <summary> /// Class that holds the properties for each result returned by the UpdateListItems webservice /// </summary> public class SingleResultBE { public string Id { get; set; } public string Operation { get; set; } public string ErrorCode { get; set; } public int ListItemId { get; set; } public string Title { get; set; } public DateTime Modified { get; set; } public DateTime Created { get; set; } public int Attachments { get; set; } public int ModerationStatus { get; set; } public string ErrorMessage { get; set; } public string ListItemGuid { get; set; } public string FileDirRef { get; set; } public string FileRef { get; set; } public string ServerUrl { get; set; } public string EncodedAbsUrl { get; set; } public string BaseName { get; set; } public const string NO_ERROR = "0x00000000"; public const string Exist_ERROR = "0x8107090d"; }
返回结果集里的ErrorCode是0x00000000表示插入成功,如果是0x8107090d表示插入的item己经存在。
接下来我们讲解update item做法和UserGroup的用法
作者:spring yang
出处:http://www.cnblogs.com/springyangwc/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。