我正在尝试从 Java 应用程序运行 GetChanges 方法 (sitedata.asmx)。但是我无法弄清楚我必须传递的正确参数。这是针对 SharePoint 2010 的。
通过检查 服务协议规范,我看到这是必需的参数:
objectType:更改跟踪空间
报告,或者
“内容数据库”或“SiteCollection”。
所有其他 objectType 值,如
第 2.2.5.3 节中定义,不得
被使用。请注意,“站点”中
该参数的上下文实际上
表示网站集。
contentDatabaseId:内容的 GUID
数据库,预先已知或获得
通过 GetContent 请求。
LastChangeId: 指定起点的标记
获取所请求的变更报告。
通常协议客户端获取
该值来自对 a 的响应
之前的 GetContent 或 GetChanges 操作。
CurrentChangeId:指定的令牌
请求的更改的端点
报告。如果不为空,则 CurrentChangeId
必须是从以下位置获得的有效令牌
对先前 GetChanges 的响应
手术。通常,该元素是
空的;空指定
协议客户端请求所有更改
从起点开始直到
现在的时间。
超时:一个值
这决定了有多少变化
应该在当前获取
手术。该值必须更大
大于 0 并且协议服务器必须
只获取总更改的 x%
默认情况下获取,其中 x 是
(超时除以 30000)。
协议客户端必须传递令牌
对应变更跟踪
由 objectType 指定的空间和
SOAP 请求的目标 URL。
我发送的 SOAP In 消息如下:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns1:GetChanges xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/">
<ns1:objectType>SiteCollection</ns1:objectType>
<ns1:contentDatabaseId>E5C5E20A-5A9F-406C-B9F6-28923750CECD</ns1:contentDatabaseId>
<ns1:startChangeId>1;0;E5C5E20A-5A9F-406C-B9F6-28923750CECD;634438121498470000;46852</ns1:startChangeId>
<ns1:Timeout>0</ns1:Timeout>
</ns1:GetChanges>
</soapenv:Body>
</soapenv:Envelope>
但是我得到了这样的响应:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Receiver</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown.</soap:Text>
</soap:Reason>
<detail>
<errorstring xmlns="http://schemas.microsoft.com/sharepoint/soap/">Object reference not set to an instance of an object.</errorstring>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
检查了来自 SharePoint 的日志(位于 Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS)并发现以下异常:
SOAP exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.SharePoint.SPChangeToken.ParseChangeToken(String strChangeToken)
at Microsoft.SharePoint.SPChangeToken..ctor(String strChangeToken)
at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(ObjectType objectType, String contentDatabaseId, String& startChangeId, String& endChangeId, Int64 maxChangesToFetch, UInt32 maxSPRequests, Boolean getMetadata, Boolean ignoreSecurityIfInherit, Int32 schemaVersion, Boolean& moreChanges)
at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(ObjectType objectType, String contentDatabaseId, String& startChangeId, String& endChangeId, Int32 Timeout, Boolean& moreChanges)
at Microsoft.SharePoint.SoapServer.SiteData.GetChanges(ObjectType objectType, String contentDatabaseId, String& LastChangeId, String& CurrentChangeId, Int32 Timeout, Boolean& moreChanges)
但是,我找不到任何对该错误的引用。我什至无法从 SPChangeToken 类中找到方法 ParseChangeToken (http ://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spchangetoken_methods.aspx),所以这很令人困惑。
我已经看到这个问题,但这并不能解决我的问题: 其他问题
任何人都可以帮助我正确调用此网络服务吗?
编辑
尝试从 C# 应用程序调用它以确定问题不在于 Java。这是代码:
SiteData.SiteDataSoapClient siteDataService = new SiteData.SiteDataSoapClient();
siteDataService.Endpoint.Address = new System.ServiceModel.EndpointAddress("URL/_vti_bin/sitedata.asmx");
siteDataService.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("username", "password", "domain");
siteDataService.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
String startChangeId = "1;1;69d025ce-96a7-4131-adc0-7da1603e8d24;634439002539570000;46914";
String endChangeId = "";
bool hasMoreChanges = false;
String databaseID = E5C5E20A-5A9F-406C-B9F6-28923750CECD; //Got it by querying SharePoint database. Any idea how to get it programatically?
String result = siteDataService.GetChanges(SiteData.ObjectType.SiteCollection, databaseID, ref startChangeId, ref endChangeId, 0, out hasMoreChanges);
return result;
但是,我收到“Microsoft.SharePoint.SoapServer.SoapServerException”,并且此异常的详细信息为空。使用 Fiddler 监视 SharePoint 服务器返回的 XML,并发现相同的“对象引用不”设置为对象异常的实例。
所以这肯定意味着我传递的参数有问题,对吧?
谢谢!!
编辑
如果有人感兴趣,我也通过在 XML 消息中将 StartChangeId 设置为 LastChangeId 并将 EndChangeId 设置为 CurrentChangeId 来完成这项工作。
I'm trying to run GetChanges method (sitedata.asmx) from a Java application. However I can't figure out the correct parameters I must pass. This is for SharePoint 2010.
By checking on the service protocol specification, I saw this are the required parameters:
objectType: The change tracking space
to report about, either
"ContentDatabase" or "SiteCollection".
All other objectType values, as
defined in section 2.2.5.3, MUST NOT
be used. Note that "Site" in the
context of this parameter actually
means site collection.
contentDatabaseId: GUID of the content
database, known in advance or obtained
by GetContent request.
LastChangeId: A token specifying the starting point
for the requested change report.
Normally the protocol client obtains
this value from the response to a
previous GetContent or GetChanges operation.
CurrentChangeId: A token specifying
the endpoint for the requested change
report. If not empty, CurrentChangeId
must be a valid token obtained from
the response to a previous GetChanges
operation. Normally, this element is
empty; empty specifies that the
protocol client requests all changes
starting from the starting point up to
the present time.
Timeout: A value
that determines how many changes
should be fetched in the current
operation. This value MUST be greater
than 0 and the protocol server MUST
only fetch x% of total changes that
are fetched by default, where x is
(Timeout divided by 30000).
The protocol client MUST pass tokens that
correspond to the change tracking
space specified by the objectType and
the target URL of the SOAP request.
The SOAP In message I'm sending is as follows:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns1:GetChanges xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/">
<ns1:objectType>SiteCollection</ns1:objectType>
<ns1:contentDatabaseId>E5C5E20A-5A9F-406C-B9F6-28923750CECD</ns1:contentDatabaseId>
<ns1:startChangeId>1;0;E5C5E20A-5A9F-406C-B9F6-28923750CECD;634438121498470000;46852</ns1:startChangeId>
<ns1:Timeout>0</ns1:Timeout>
</ns1:GetChanges>
</soapenv:Body>
</soapenv:Envelope>
However I get this response:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Receiver</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown.</soap:Text>
</soap:Reason>
<detail>
<errorstring xmlns="http://schemas.microsoft.com/sharepoint/soap/">Object reference not set to an instance of an object.</errorstring>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Checked the logs from SharePoint (located at Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS) and found the following exception:
SOAP exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.SharePoint.SPChangeToken.ParseChangeToken(String strChangeToken)
at Microsoft.SharePoint.SPChangeToken..ctor(String strChangeToken)
at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(ObjectType objectType, String contentDatabaseId, String& startChangeId, String& endChangeId, Int64 maxChangesToFetch, UInt32 maxSPRequests, Boolean getMetadata, Boolean ignoreSecurityIfInherit, Int32 schemaVersion, Boolean& moreChanges)
at Microsoft.SharePoint.SoapServer.SiteDataImpl.GetChanges(ObjectType objectType, String contentDatabaseId, String& startChangeId, String& endChangeId, Int32 Timeout, Boolean& moreChanges)
at Microsoft.SharePoint.SoapServer.SiteData.GetChanges(ObjectType objectType, String contentDatabaseId, String& LastChangeId, String& CurrentChangeId, Int32 Timeout, Boolean& moreChanges)
However, I'm not able to find any references to that error. I can't even found the method ParseChangeToken from SPChangeToken class (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spchangetoken_methods.aspx), so this is confusing.
I already saw this question, however this doesn't solve my issue: Other question
Can anyone help me calling this web service correctly?
EDIT
Tried calling it from a C# application to determine that the issue is not with Java. This is the code:
SiteData.SiteDataSoapClient siteDataService = new SiteData.SiteDataSoapClient();
siteDataService.Endpoint.Address = new System.ServiceModel.EndpointAddress("URL/_vti_bin/sitedata.asmx");
siteDataService.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("username", "password", "domain");
siteDataService.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
String startChangeId = "1;1;69d025ce-96a7-4131-adc0-7da1603e8d24;634439002539570000;46914";
String endChangeId = "";
bool hasMoreChanges = false;
String databaseID = E5C5E20A-5A9F-406C-B9F6-28923750CECD; //Got it by querying SharePoint database. Any idea how to get it programatically?
String result = siteDataService.GetChanges(SiteData.ObjectType.SiteCollection, databaseID, ref startChangeId, ref endChangeId, 0, out hasMoreChanges);
return result;
However, I got 'Microsoft.SharePoint.SoapServer.SoapServerException' and the detail of this exception is null. Used Fiddler to spy on the XML returned by the SharePoint server, and found the same 'Object reference not set to an instance of an object' exception.
So this certainly means there is something wrong with the parameters I'm passing, right?
Thanks!!
Edit
If someone is interested, I made this work too by setting StartChangeId to LastChangeId and EndChangeId to CurrentChangeId in the XML message.
解决了。通过检查 SharePoint 日志,我注意到以下几行:
注意第二行,内容数据库 ID 由“{}”字符括起来。另请注意,“contentDbId”已从传入的 XML 中正确解析,而“endChange”为空。第二个观察结果可能是导致“对象引用未设置到对象实例”异常的原因。那么,这个changeId有什么问题呢?不知道,XML 编码可能存在问题,导致 SharePoint 无法正确解析changeId。
通过进一步查看同一个日志,我发现了以下几行:
Here,changeId 是从传入的 XML 中正确解析的。因此,我从 GetChanges() 方法更改为 GetChangesEx(),传递了我在前一次调用中使用的完全相同的参数,并且它工作正常!我的猜测是,由于参数被编码在 SOAP In 请求的元素内,因此 Web 服务能够正确解析它们。
以下是最终的 SOAP In 消息(已格式化):
编辑
C# 代码示例:
Solved it. By checking on the SharePoint logs, I noticed the following lines:
Notice on the second line, that the content database Id is enclosed by "{}" characters. Also, see that "contentDbId" is parsed correctly from the incoming XML, while "endChange" is empty. This second observation, is probably what leads to the "Object reference not set to an instance of an object" exception. So, what is wrong with that changeId? No idea, probably there is something wrong with the XML encoding that prevents SharePoint from parsing the changeId correctly.
By further looking on the same log, I found this lines:
Here, the changeId is correctly parsed from the incoming XML. So, I changed from GetChanges() method to GetChangesEx(), passed the exact same parameters I was using on the former call, and it worked correctly!! My guess is that because the parameters are encoded inside an element of the SOAP In request, the Web Service is able to parse them correctly.
Here is the final SOAP In message (formatted):
Edit
C# code example: