Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening WebDAV documents as read-only in MS Office with IT Hit WebDAV Server

I'm creating a solution for managing remote MS Office documents. I used library made by IT Hit WebDAV System (www.webdavsystem.com) as a prototype. It's doing pretty well actually, except I cannot open document in read-only mode using URIs for office (based on Office URI Schemes by Microsoft).

I want to open the document in read-only mode, so someone else can edit it in the same time. As it can be seen in B-3. URI Scheme Syntax part of mentioned documentation, there are three commands available:

  • ofe - open for edit
  • ofv - open for view
  • nft - new from template

It seems that server acts always as "ofe" commands was given, no matter which one was used. Actually, entering "whatever" also works, it can be literally everything. Using MS Word for example, I post request order below:

OPTIONS => HEAD => OPTIONS => OPTIONS => LOCK => GET => PROPFIND => OPTIONS

As I am understanding correctly, successful LOCK attempt results in opening the document in edit mode. That tells me, that somewhere before that point MS WORD should ask for permission to do it, but I analyzed previous requests and was unable to find any related data.
It is not my environment issue also. I checked it with SharePoint and it was ok. That's why I would blame the server.

As I read that sentence(below) in this question,

most WebDAV clients ignore this and pretend that the entire server is either read-write or read-only

I started to wonder. Maybe that's the case? Maybe the library skips that and treats every file as read-write? If yes, how can I check it to be sure?

I've checked also this topic. The author mentions, that he has Office URI command in his OPTIONS requests, but links are no longer valid. In the requests that are sent by MS Office 2016, I can't find it anywhere. Should it be anywhere? Where?

Last, but not least, I found this topic. It seems to be exactly my problem, but it don't have the solution mentioned, or at least anything that worked in my case.

I will appreciate any help.

like image 545
Mike Sar Avatar asked Oct 15 '25 03:10

Mike Sar


2 Answers

We have recently retested ofv and ofe options with latest MS Office 2016 for Windows and for Mac OS X with all updates installed. Here is what we have found:

  • On Windows this option is being ignored. Regardless of this parameter MS Office opens as read-write.
  • On Mac OS this option is required. MS Office respects this option and opens depending on ofv/ofe as read-only or read-write.

From our experience there is no reliable way to open a document as read-only. In SharePoint Online (SPS 2016) there is also no option to open a document as read-only in the desktop version of MS Office.

One workaround could be throwing DavException in IFileAsync.WriteAsync() method implementation when saving a file. Please note that MS Office will ignore the message text being returned and will just display a generic error.

Another workaround would be marking a document as read-only in IMsItemAsync.GetFileAttributesAsync() method implementation:

    public async Task<FileAttributes> GetFileAttributesAsync()
    {
        return fileSystemInfo.Attributes | FileAttributes.ReadOnly;
    }

MS Office will display a yellow ribbon "UPLOAD FAILED This file is locked for editing by another user".

like image 152
IT Hit WebDAV Avatar answered Oct 17 '25 18:10

IT Hit WebDAV


The solution i came up with is to prevent the lock but with a specific exception.

When creating the file from the backend using the IT Hit .NET client, I attach a custom property to the file to indicate whether it's read-only. Here's how:

 fileResponse = await fileIndexIdGuidFolder.CreateFileAsync(filename);
 file = fileResponse.WebDavResponse;
 
 //Add properties to the webdavfile 
 Property isReadOnlyProperty = new Property(new PropertyName("isReadOnly", "PraiseTheSun"), isReadOnly.ToString());

 Property[] webDavProperties = new Property[1];
 webDavProperties[0] = isReadOnlyProperty;


 await file.UpdatePropertiesAsync(webDavProperties,null);

From the frontend, you can open the document using IT Hit's Ajax library or ms schemas as href links (adjust the URL accordingly). Below you can find implementations for both those methods (the commented out lines are the ms schema implementation)

     function OpenOrEditDocument(documentUrl) 
     {
         // let linkToDocument = document.createElement('a');

         // // Set the href attribute to the document URL
         // linkToDocument.href = documentUrl;

         // // Set display style to none to hide it
         // linkToDocument.style.display = 'none';

         // // Append the link to the body
         // document.body.appendChild(linkToDocument);

         // // Trigger the click event
         // linkToDocument.click();

         // // Remove the link from the DOM after the click
         // document.body.removeChild(linkToDocument);

         ITHit.WebDAV.Client.DocManager.MicrosoftOfficeEditDocument(documentUrl);
     }
                    
     });

Finally, in the ITHIt WebDAV Class 2 server implementation (https://www.webdavsystem.com/server/documentation/creating_class_2_webdav_server/) in the LockAsync method, retrieve the file property and throw an exception.

Important: You must throw a DavException with DavStatus.FORBIDDEN. Otherwise, Office may proceed to open the document in edit mode, which defeats the purpose.

  public async Task<LockResult> LockAsync(LockLevel level, bool isDeep, TimeSpan? requestedTimeOut, string owner)
  {

      //Retrieve the properties that i passed to the file when i created it
      var properties = await this.GetPropertyValuesAsync();

      //Retrieve the isReadOnly property and convert it to boolean
      var documentIsReadOnlyToString = properties?.FirstOrDefault(p => p.QualifiedName.Name == "isReadOnly")?.Value;
      bool isReadonly = string.IsNullOrEmpty(documentIsReadOnlyToString) ? false : Convert.ToBoolean(documentIsReadOnlyToString);

      //If the document has a readonly property then i throw an exception so the document will not be locked and opened in readonly mode
      if (isReadonly)
      {
          // Prevent locks on read-only documents
          throw new DavException("This document is read-only.", DavStatus.FORBIDDEN);
      }
//rest of the code
}

Hope that helps!!!

like image 26
NIKOLAOS ANDREOPOULOS Avatar answered Oct 17 '25 18:10

NIKOLAOS ANDREOPOULOS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!