步步为营 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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的结果集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /// <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取得我们需要的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /// <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定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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的定义如下,保存返回的结果集
1 2 3 4 5 6 7 8 9 10 11 12 | 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格式
1 2 3 4 5 6 7 8 9 10 | <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格式如下
1 2 3 4 5 6 7 8 9 | <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方法来做如下处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /// <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(); } |
调用方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /// <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定义如下,它是用来获取返回我们想要的结果集。
返回结果集格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <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> |
我们取结果的方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | /// <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就是我们想要的结果集.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /// <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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)