开发者

Word 2010 reports an error after saving to WebDAV server

开发者 https://www.devze.com 2023-04-03 05:41 出处:网络
I\'ve got a custom WebDAV server, built using Sphoirum webdav server, that resides inside an ASP.NET MVC3 application. It\'s a .Net 4.0 project.

I've got a custom WebDAV server, built using Sphoirum webdav server, that resides inside an ASP.NET MVC3 application. It's a .Net 4.0 project.

The document repository is a SharePoint, where our MVC application is a front end to it, and exposes the whole thing via the WebDAV. Just to note we don't have WebDAV publishing enabled on our IIS 7.5.

I've implemented the following HTTP verbs:

  • Get

  • Head

  • Lock

  • Options

  • PropFind

  • Put

  • Unlock

Now, when I open a word document, it's first in the read only mode. Getting the lock and into edit mode is successful, but when I want to save the changes in my document I get the following:

Your changes were saved but could not be uploaded because of an error.

The trick is that document is indeed saved correctly to the repository, and the response from our WebDAV server to word is HTTP/200 but the Word complains nonetheless. I've also tried editing in Word directly from the SharePoint repository, just to confirm that my Office isn't broken somehow - all works.

Here's the response from PUT request when saving the document from 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: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=/

And here's the same response, for the same document, from our WebDAV server:

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

So I've tried to mimic some of the headers SharePoint emits, like MicrosoftSharePointTeamServices but to no avail.


By the way, I found the bug in Sphorium webdav that was causing this. The bug was in the method DavLockBase_InternalProcessDavRequest() and the incorrect line of code was:

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

which should be:

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

After that change, saving files in Word 2010 worked fine.


If someone ever runs into this again, here is a fix that was built based on the above answer, and on what I have found from working with word 2010. Basically the fix involves replacing the code for the "DavLockBase_InternalProcessDavRequest" method (I've added some comments for each "correction").

As a note (found some info here): the behavior of the webdav implementation for word 2010 differs on whether there is a patch installed on the client side or not; therefore the 3rd correction may not be needed in all cases!

Hope it helps!

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


Observation: the lock token uses an invalid syntax (so does Sharepoints). Also; most of these headers shouldn't be needed (being proprietary) or do not apply to a PUT response (such as Lock-Token).

I would recommend to try publishing to Apache with mod_dav first, and to observe the HTTP exchange.

0

精彩评论

暂无评论...
验证码 换一张
取 消