2011-09-08 59 views
4

我有一個自定義的WebDAV服務器,使用Sphoirum webdav服務器構建,駐留在ASP.NET MVC3應用程序中。這是一個.Net 4.0項目。Word 2010在保存到WebDAV服務器後報告錯誤

文檔庫是一個SharePoint,我們的MVC應用程序是它的前端,並通過WebDAV公開了整個事情。請注意,我們的IIS 7.5上沒有啓用WebDAV發佈。

我已經實現了以下HTTP動詞:

  • 獲取

  • 鎖定
  • 選項
  • PROPFIND

  • 解鎖

現在,當我打開一個word文檔時,它首先處於只讀模式。獲取該鎖,並進入編輯模式是成功的,但是當我要救我的文件中的變化,我得到如下:

您的更改保存,但因爲錯誤而無法上傳。

訣竅是,文件是確實正確保存到存儲庫,並從我們的WebDAV服務器來字的響應HTTP/200,但話語仍然抱怨。 我也嘗試直接從SharePoint存儲庫中編輯Word,只是爲了確認我的辦公室不會以某種方式破碎 - 所有的作品。

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:[email protected] 
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:[email protected] 
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 

所以我

這裏保存時從Word文檔的從PUT請求的響應我試圖模仿SharePoint發出的一些頭文件,如MicrosoftSharePointTeamServices,但無濟於事。

回答

3

順便說一下,我發現Sphorium webdav中的錯誤導致了這種情況。該缺陷是在方法DavLockBase_InternalProcessDavRequest()和代碼不正確的路線是:

string[] _lockTokens = this.RequestLock.GetLockTokens(); 

這應該是:

string[] _lockTokens = this.ResponseLock.GetLockTokens(); 

這一變化後,節省了在Word 2010文件工作得很好。

0

觀察:鎖定令牌使用無效的語法(Sharepoints也是如此)。也;大多數這些標題不應該被需要(專有)或不適用於PUT響應(例如鎖定令牌)。

我建議嘗試首先使用mod_dav發佈到Apache,並觀察HTTP交換。

+0

我知道鎖定令牌不符合RFC2518規範。到信,但我試圖使服務器與Office和SharePoint一起工作。所以,如果他們錯了,我也必須:) – Vanja

+0

(一)你需要看看現在的RFC 4918。 (b)幾年前曾與通用WebDAV服務器合作的辦公室;也許他們打破了它,但在嘗試模仿Sharepoint之前,值得一試。 –

+0

好點。我會看看它。問題是Sphorium實現了2518,但我有它的源代碼,所以應該可以添加更多的擴展。 – Vanja

1

如果有人再次遇到這個問題,這裏是基於上述答案構建的一個修復程序,以及我從使用單詞2010時發現的一個修復程序。基本上修復涉及替換「DavLockBase_InternalProcessDavRequest」方法的代碼(我已經爲每個「更正」添加了一些評論)。

作爲說明(發現一些信息here):word 2010的webdav實施行爲因客戶端是否安裝了補丁而不同;因此在所有情況下可能不需要第三次更正!

希望它有幫助!

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; 
    }