Word 2010在保存到WebDAV服务器后报告错误
本文关键字:服务器 报告 错误 WebDAV 2010 保存 Word | 更新日期: 2023-09-27 18:07:52
我有一个自定义的WebDAV服务器,使用Sphoirum WebDAV服务器构建,驻留在一个ASP。NET mvc应用程序。这是一个。net 4.0项目。
文档存储库是一个SharePoint,我们的MVC应用程序是它的前端,并通过WebDAV公开全部内容。要注意的是,我们没有在IIS 7.5上启用WebDAV发布。
我实现了以下HTTP动词:
- 得到
- 头
- 锁
- PropFind
- 把
- 解锁
现在,当我打开一个word文档时,它首先处于只读模式。锁定并进入编辑模式是成功的,但是当我想保存文档中的更改时,我得到以下内容:
技巧在于文档确实正确地保存到存储库中,并且我们的WebDAV服务器对word的响应是HTTP/200,但是word仍然抱怨。我也试过直接从SharePoint存储库中编辑Word,只是为了确认我的Office没有坏掉——一切正常。您的更改已保存,但由于错误而无法上传。
下面是从Word保存文档时PUT请求的响应:
HTTP/1.1 200 OK
Date: Tue, 06 Sep 2011 12:25:47 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 12.0.0.6545
Last-Modified: Tue, 06 Sep 2011 12:25:47 GMT
ETag: "{F4A63494-D302-4C9B-9C57-D0CB0937A2B0},9"
ResourceTag: rt:F4A63494-D302-4C9B-9C57-D0CB0937A2B0@00000000009
X-MSDAVEXTLockTimeout: Second-3600
Lock-Token: opaquelocktoken:{F4A63494-D302-4C9B-9C57-D0CB0937A2B0}20110906T122532Z
Expires: Mon, 22 Aug 2011 12:25:47 GMT
Cache-Control: private,max-age=0
Content-Length: 0
Public-Extension: http://schemas.microsoft.com/repl-2
Set-Cookie: WSS_KeepSessionAuthenticated=40689; path=/
对于同一个文档,WebDAV服务器给出了相同的响应:
HTTP/1.1 200 OK
Cache-Control: private,max-age=0
Content-Length: 0
Expires: Wed, 24 Aug 2011 08:03:28 GMT
Last-Modified: Wed, 07 Sep 2011 08:03:28 GMT
ETag: "{4a4331a8-7df6-43e6-bd5f-bb80765e83a2},1"
Server: Microsoft-IIS/7.5
MS-Author-Via: DAV
ResourceTag: rt:4a4331a8-7df6-43e6-bd5f-bb80765e83a2@00000000001
Lock-Token: opaquelocktoken:{4a4331a8-7df6-43e6-bd5f-bb80765e83a2}20110907T080328Z
X-MSDAVEXTLockTimeout: Second-3600
Public-Extension: http://schemas.microsoft.com/repl-2
MicrosoftSharePointTeamServices: 12.0.0.6545
Set-Cookie: WSS_KeepSessionAuthenticated=40689; path=/
X-Powered-By: ASP.NET
Date: Wed, 07 Sep 2011 08:03:27 GMT
所以我试着模仿SharePoint发出的一些头,如MicrosoftSharePointTeamServices但无济于事。
顺便说一下,我在Sphorium webdav中发现了导致这种情况的错误。错误在方法DavLockBase_InternalProcessDavRequest()中,错误的代码行是:
string[] _lockTokens = this.RequestLock.GetLockTokens();
应该是:
string[] _lockTokens = this.ResponseLock.GetLockTokens();
更改后,在Word 2010中保存文件可以正常工作。
如果有人再次遇到这种情况,这里有一个基于上述答案的修复方法,以及我在使用word 2010时发现的问题。基本上,修复涉及替换"DavLockBase_InternalProcessDavRequest"方法的代码(我为每个"更正"添加了一些注释)。
作为一个说明(在这里找到一些信息):webdav实现的word 2010的行为不同,是否有一个补丁安装在客户端或没有;因此,并非所有情况下都需要第三次修正!
希望有帮助!
private int DavLockBase_InternalProcessDavRequest(object sender, EventArgs e)
{
int _responseCode = (int)DavLockResponseCode.Ok;
//string[] _lockTokens = this.RequestLock.GetLockTokens();
//#1 the above line is incorrect. replaced with the following:
string[] _lockTokens = this.ResponseLock.GetLockTokens();
//Check to see if a lock refresh was requested
if (base.HttpApplication.Request.Headers["If"] != null)
{
if (_lockTokens.Length == 1)
{
//#2 not sure why this should be done (or not), however I've seen this in other people corrections.
//DavRefreshEventArgs _refreshEventArgs = new DavRefreshEventArgs(_lockTokens[0], this.RequestLock.LockTimeout);
//OnRefreshLockDavRequest(_refreshEventArgs);
}
base.HttpApplication.Response.AppendHeader("Timeout", "Second-" + this.ResponseLock.LockTimeout);
}
else
{
//New lock request
StringBuilder _opaquelockTokens = new StringBuilder();
//#3 finally, added the check below, as most of the times, when using word 2010 there are no lock requests
if (_lockTokens.Length > 0)
{
foreach (string _lockToken in _lockTokens)
_opaquelockTokens.Append("<opaquelocktoken:" + _lockToken + ">");
base.HttpApplication.Response.AppendHeader("Lock-Token", _opaquelockTokens.ToString());
}
}
//Check to see if there were any process errors...
Enum[] _errorResources = this.ProcessErrorResources;
if (_errorResources.Length > 0)
{
//Append a response node
XmlDocument _xmlDocument = new XmlDocument();
XmlNode _responseNode = _xmlDocument.CreateNode(XmlNodeType.Element, _xmlDocument.GetPrefixOfNamespace("DAV:"), "response", "DAV:");
//Add the HREF
XmlElement _requestLockHrefElement = _xmlDocument.CreateElement("href", "DAV:");
_requestLockHrefElement.InnerText = base.RelativeRequestPath;
_responseNode.AppendChild(_requestLockHrefElement);
//Add the propstat
XmlElement _propstatElement = _xmlDocument.CreateElement("propstat", "DAV:");
XmlElement _propElement = _xmlDocument.CreateElement("prop", "DAV:");
XmlElement _lockDiscoveryElement = _xmlDocument.CreateElement("lockdiscovery", "DAV:");
_propElement.AppendChild(_lockDiscoveryElement);
_propstatElement.AppendChild(_propElement);
XmlElement _statusElement = _xmlDocument.CreateElement("status", "DAV:");
_statusElement.InnerText = InternalFunctions.GetEnumHttpResponse(DavLockResponseCode.FailedDependency);
_propstatElement.AppendChild(_statusElement);
_responseNode.AppendChild(_propstatElement);
base.SetResponseXml(InternalFunctions.ProcessErrorRequest(this.ProcessErrors, _responseNode));
_responseCode = (int)ServerResponseCode.MultiStatus;
}
else
{
//No issues
using (Stream _responseStream = new MemoryStream())
{
XmlTextWriter _xmlWriter = new XmlTextWriter(_responseStream, new UTF8Encoding(false));
_xmlWriter.Formatting = Formatting.Indented;
_xmlWriter.IndentChar = ''t';
_xmlWriter.Indentation = 1;
_xmlWriter.WriteStartDocument();
//Open the prop element section
_xmlWriter.WriteStartElement("D", "prop", "DAV:");
_xmlWriter.WriteStartElement("lockdiscovery", "DAV:");
this.ResponseLock.ActiveLock.WriteTo(_xmlWriter);
_xmlWriter.WriteEndElement();
_xmlWriter.WriteEndElement();
_xmlWriter.WriteEndDocument();
_xmlWriter.Flush();
base.SetResponseXml(_responseStream);
_xmlWriter.Close();
}
}
return _responseCode;
}
观察:锁令牌使用了无效的语法(Sharepoints也是如此)。也;这些报头中的大多数不应该被需要(是专有的),或者不适用于PUT响应(如Lock-Token)。
我建议先尝试使用mod_dav发布到Apache,并观察HTTP交换