Creating Class 2 WebDAV Server

In addition to the functionality provided by Class 1 server, Class 2 server allows hierarchy items locking. Items locking may help to prevent server items modification by other users.

To create class 2 server you mast implement additional interfaces on you hierarchy items and provide a new type of hierarchy item – lock-null item. In class 2 server implementation before modifying any server items, you must check if the item is not locked or if WebDAV client provided the necessary lock token. From your Engine.GetHierarchyItem method in addition to folder and resource items you must also return lock-null items:

public override IHierarchyItem GetHierarchyItem(string path)

{
    string discPath = ConfigurationManager.AppSettings["StorageRootFolder"].TrimEnd('\\');
    discPath += path.Replace('/', '\\');

    DirectoryInfo directory = new DirectoryInfo(discPath);
    if(directory.Exists)
        return new Folder(directory);

    else

    {
        FileInfo file = new FileInfo(discPath);
        if(file.Exists)
        {
            if ( (file.Attributes & FileAttributes.Temporary) != 0)
                return new LockNull(file); // lock-null item
            else
                return new Resource(file);
        }
    }
    return null;
}

On you resource items you must additionally implement ILock interface and on folder items - IFolderLock interface.

WebDAV server Class 2 core classes diagram

ILock interface provides the means for locking the hierarchy item and accessing the list of applied locks. When WebDAV client issues lock request WebDAV engine calls ILock.Lock method passing LockInfo structure by reference. In your ILock implementation, you must generate the new lock token (usually a GUID), associate the lock token with the item in the repository and return the lock token to the engine. The engine then sends it back to WebDAV client.

When WebDAV client is modifying any server item it sends to the server the list of lock tokens. These tokens are accessible via Request.ClientLockTokens property. In your WebDAV server Class 2 implementation before modifying any locked items, you must check if WebDAV client provided necessary lock token for this item.

WebDAV server lock tokens

The new types of items - lock-null items are used to lock name before resource or folder creation. WebDAV client may issue lock-null creation request first and then resource or folder creation request. However the client can also issue folder and resource creation requests without creating a lock-null item.

Lock-null items inherit ILockNull interface. This interface provides 2 methods for converting a lock-null item to a folder or resource. Lock-nulls are created during a call to IFolderLock.CreateLockNull method and converted to a resource or folder during a call to ILockNull.ConvertToResource or ILockNull.ConvertToFolder methods. A lock-null item can not be moved, copied or deleted. If such item was not converted to a resource or folder it can be deleted during a call to ILock.Unlock method.

ILockNull sample implementation:

public class LockNull : HierarchyItem, ILockNull
{
    public LockNull(FileInfo file)
        : base(file)
    {
    }
 
    public WebDAVResponse ConvertToResource()
    {
        FileInfo file = (FileInfo)fileSystemInfo;
 
        file.Attributes &= ~FileAttributes.Temporary; // remove lock-null marker
 
        return new CreatedResponse();
    }
 
    public WebDAVResponse ConvertToFolder()
    {
        FileInfo file = (FileInfo)fileSystemInfo;
        string path = file.FullName;
        file.Delete();
        Directory.CreateDirectory(path);
 
        return new CreatedResponse();
    }
 
    public override WebDAVResponse CopyTo(IFolder folder, string destName, bool deep)
    {
        return new NotAllowedResponse();
    }
 
    public override WebDAVResponse MoveTo(IFolder folder, string destName)
    {
        return new NotAllowedResponse();
    }
 
    public override WebDAVResponse Delete()
    {
        return new NotAllowedResponse();
    }
 
    public override WebDAVResponse UpdateProperties(Property[] setProps, Property[] delProps)
    {
        return new NotAllowedResponse();
    }
}