概要
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的用法