WebDAVClient 2.7.0

dotnet add package WebDAVClient --version 2.7.0
                    
NuGet\Install-Package WebDAVClient -Version 2.7.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WebDAVClient" Version="2.7.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WebDAVClient" Version="2.7.0" />
                    
Directory.Packages.props
<PackageReference Include="WebDAVClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WebDAVClient --version 2.7.0
                    
#r "nuget: WebDAVClient, 2.7.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WebDAVClient@2.7.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WebDAVClient&version=2.7.0
                    
Install as a Cake Addin
#tool nuget:?package=WebDAVClient&version=2.7.0
                    
Install as a Cake Tool

WebDAVClient

Overview

WebDAV Client for .Net Core, strongly typed, async and open-sourced, implemented in C#.

WebDAVClient is based originally on https://github.com/kvdb/WebDAVClient. I've added Async support (instead of Callback), as well strong-types responses.

NuGet

WebDAVClient is available as a NuGet package

Features

  • Available as a NuGet package
  • Fully support Async/Await
  • Strong-typed
  • Implemented using HttpClient, which means support for extendibility such as throttling and monitoring
  • Authentication: unauthenticated, Windows / Basic / Digest (via ICredentials), and Bearer / OAuth 2.0 (via static token or async refreshable provider)
  • Supports custom Certificate validation
  • Supports the full WebDAV API:
    • Retrieving files & folders
    • Listing items in a folder (<allprop/>, targeted <prop>, and <propname/> PROPFIND variants)
    • Creating & deleting folders
    • Downloading & uploading files
    • Downloading & uploading partial content
    • Moving & copying files and folders (with the Overwrite header and optional destination lock-token)
    • Locking & unlocking resources (LOCK / UNLOCK / RefreshLock) with a strongly-typed LockInfo
    • Setting & removing custom (dead) properties via PROPPATCH
    • Discovering server capabilities via OPTIONS (DAV compliance classes + allowed methods)
    • Submitting WebDAV lock tokens through the If header on PUT / DELETE / MOVE / COPY

Release Notes

  • 2.7.0 (upcoming) Security & hardening:
    • WebDAV LOCK / UNLOCK (RFC 4918 §9.10–9.11): new LockFile / LockFolder / UnlockFile / UnlockFolder / RefreshLock methods returning a strongly-typed LockInfo.
    • WebDAV PROPPATCH (RFC 4918 §9.2): new SetProperty / RemoveProperty methods for managing custom (dead) properties.
    • Bug fix — Overwrite header on COPY / MOVE (RFC 4918 §9.8.3 / §9.9.3): always sent (default T); new optional overwrite parameter to opt out. 204 No Content accepted as success.
    • Bug fix — Depth: infinity on DELETE (RFC 4918 §9.6.1): now sent as required by the spec for collection deletes.
    • If lock-token submission on PUT / DELETE / MOVE / COPY (RFC 4918 §10.4): new optional lockToken (and source / destination variants) parameters so locked-resource servers no longer reject modifications with 423 Locked.
    • Internal refactor: extracted the static helpers in Client.cs into focused, unit-testable helper classes under WebDAVClient.Helpers. No public-API change.
    • PROPFIND request-body variants (RFC 4918 §9.1): new overloads to request a targeted <prop> set or discover property names via <propname/>, in addition to the existing <allprop/> behaviour.
    • HTTP OPTIONS support (RFC 4918 §9.1, RFC 9110 §9.3.7): new GetServerOptions method returning a strongly-typed ServerOptions (DAV compliance classes + allowed methods).
    • Bearer token / OAuth 2.0 authentication: new Client constructor overloads — static token or async refreshable provider — backed by a public WebDAVClient.Authentication.BearerTokenAuthenticationHandler.
    • XXE hardening: ResponseParser now sets DtdProcessing = Prohibit and XmlResolver = null explicitly.
    • Certificate validation wired: ServerCertificateValidationCallback is now actually plumbed into the underlying HttpClientHandler.
    • SSRF protection: BuildServerUrl validates that any absolute URI it accepts belongs to the configured Server host.
    • Header injection protection: CustomHeaders entries are validated for CR/LF in both name and value before being sent.
  • 2.5.x Performance & bug-fix rollup:
    • List() no longer issues an await GetServerUrl per returned item — the encoded base path is resolved once and reused, dramatically reducing async overhead on large listings.
    • CustomHeaders and the internal headers dictionary are no longer copied or double-looked-up per request; they are iterated in place.
    • Cached static byte arrays for the MOVE/COPY request bodies and PROPFIND body to eliminate per-call allocations.
    • ResponseParser avoids a per-node string allocation when reading element local names.
    • Bug fix: parent-folder URL comparison in List() now uses OrdinalIgnoreCase instead of CurrentCultureIgnoreCase — avoids the Turkish dotted/dotless I issue and the slower culture-aware path.
    • Bug fix: when uploadTimeout is set, the upload HttpClient no longer disposes the HttpClientHandler it shares with the main client.
    • Added a WebDAVClient.UnitTests project covering the public surface.
  • 2.4.0 Framework support update:
    • Added support for .NET 10
    • Dropped support for .NET 9 (STS); supported targets are now .NET 8 (LTS) and .NET 10 (LTS)
  • 2.3.0 Framework support update:
    • Updated to .NET Core 8.0 and 9.0; dropped older targets
    • Packaging cleanup
  • 2.2.1 Minor packaging improvements
  • 2.2.0 Improvement:
    • Implement IDisposable to avoid HttpClient leak
    • Added support for CancellationToken
    • Various performance improvements to reduce memory allocations
    • Minor code cleanup
  • 2.1.0 Bug fixes: Fixed handling of port
  • 2.0.0 BREAKING CHANGES!!!
    • Added support for .Net Core 3.0 & .Net Standard 2.0
  • 1.1.3 Improvement:
    • Ignore WhiteSpaces while parsing response XML
    • Enable Windows Authentication
    • Support curstom certificate validation
    • Add download partial content
    • Improved testability by using a wrapper for HttpClient
  • 1.1.2 Improvements:
    • Make WebDAVClient work on Mono and make NuGet compatible with Xamarin projects
    • Provide a IWebProxy parameter for HttpClient
    • Change type of ContentLength from int to long
    • Improved compatibility to SVN
  • 1.1.1 Improvements:
    • Improved parsing of server responses
    • Improved the way we calculate URLs
  • 1.1.0 Improvement: Improved parsing of server values
  • 1.0.23 Improvement: Improve the way we handle path with "invalid" characters
  • 1.0.22 Bug fixes and improvements:
    • Improved the way we identify the root folder
    • Fixed calculation of URLs
  • 1.0.20 Improvements:
    • Added support for default/custom UserAgent
    • Improved ToString method of WebDAVException
  • 1.0.19 Improvement: Added support for uploads timeout
  • 1.0.18 Improvement: Added MoveFolder and MoveFile methods
  • 1.0.17 Improvement: Added DeleteFolder and DeleteFile methods
  • 1.0.16 Improvements:
    • Improved filtering of listed folder
    • Disable ExpectContinue header from requests
  • 1.0.15 Bug fixes: Trim trailing slashes from HRef of non-collection (files) items
  • 1.0.14 BREAKING CHANGES: Replaced Get() method with separated GetFolder() and GetFile() methods.
  • 1.0.13 Improvement: Replaced deserialization mechanism with a more fault-tolerant one.
  • 1.0.12 Bug fixes: Removed disposing of HttpMessageResponse when returning content as Stream
  • 1.0.11 Improvements:
    • Introduced new IClient interface
    • Added new WebDAVConflictException
    • Dispose HttpRequestMessage and HttpResponseMessage after use
  • 1.0.10 Bug fixes: Correctly handle NoContent server responses as valid responses
  • 1.0.9 Bug fixes: Improved handling of BasePath
  • 1.0.8 Bug fixes: Handle cases when CreationDate is null
  • 1.0.7 Async improvements: Added ConfigureAwait(false) to all async calls
  • 1.0.5 Bug fixes and improvements:
    • Decode Href property of files/folders
    • Complete Http send operation as soon as headers are read
  • 1.0.3 Various bug fixes.
  • 1.0.1 Improved error handling and authentication
  • 1.0.0 Initial release.

Usage

Client implements IDisposable — wrap it in a using to make sure the underlying HttpClient/HttpClientHandler are released. Most async methods accept an optional CancellationToken so requests can be cancelled cleanly.

// Pick one of the constructors below.

// (1) Basic authentication
using IClient client = new Client(
    new NetworkCredential { UserName = "USERNAME", Password = "PASSWORD" });

// (2) ...or no authentication
// using IClient client = new Client(new NetworkCredential());

// (3) ...or supply your own HttpClient (e.g. for IHttpClientFactory / DI scenarios)
// using IClient client = new Client(myHttpClient);

// (4) ...or Bearer / OAuth 2.0 — see "What's new in 2.7.0" below for refresh-aware variant
// using IClient client = new Client("eyJ0eXAiOiJKV1Qi...");

// Set basic information for the WebDAV provider
client.Server = "https://dav.example.com/";
client.BasePath = "/dav/";

// Optional configuration
client.Port = 8443;                                   // override the default port
client.UserAgent = "MyApp";                           // override the default User-Agent
client.CustomHeaders = new[]                          // sent with every request
{
    new KeyValuePair<string, string>("X-Tenant", "acme"),
};

// Most operations accept a CancellationToken
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var token = cts.Token;

// List items in the root folder
var files = await client.List(cancellationToken: token);

// Find folder named 'Test'
var folder = files.FirstOrDefault(f => f.Href.EndsWith("/Test/"));
// Reload folder 'Test'
var folderReloaded = await client.GetFolder(folder.Href, cancellationToken: token);

// Retrieve list of items in 'Test' folder
var folderFiles = await client.List(folderReloaded.Href, cancellationToken: token);
// Find first file in 'Test' folder
var folderFile = folderFiles.FirstOrDefault(f => f.IsCollection == false);

var tempFileName = Path.GetTempFileName();

// Download item into a temporary file
using (var tempFile = File.OpenWrite(tempFileName))
using (var stream = await client.Download(folderFile.Href, cancellationToken: token))
    await stream.CopyToAsync(tempFile, token);

// Upload file back to webdav
var tempName = Path.GetRandomFileName();
using (var fileStream = File.OpenRead(tempFileName))
{
    var fileUploaded = await client.Upload(folder.Href, fileStream, tempName, cancellationToken: token);
}

// Create a folder
var tempFolderName = Path.GetRandomFileName();
var isfolderCreated = await client.CreateDir("/", tempFolderName, cancellationToken: token);

// Copy a file
await client.CopyFile(folderFile.Href, "/" + tempFolderName + "/copy.bin", cancellationToken: token);

// Copy a folder
await client.CopyFolder(folder.Href, "/" + tempFolderName + "-copy/", cancellationToken: token);

// Delete created folder
var folderCreated = await client.GetFolder("/" + tempFolderName, cancellationToken: token);
await client.DeleteFolder(folderCreated.Href, cancellationToken: token);

What's new in 2.7.0

Bearer token / OAuth 2.0 authentication

// Static token (Nextcloud app-password, long-lived service token, …)
using IClient client = new Client("eyJ0eXAiOiJKV1Qi...");

// Async, refreshable token provider (Azure AD / MSAL / IdentityModel / custom)
using IClient client = new Client(async ct => await tokenSource.GetTokenAsync(ct));

Returning null / empty from the provider omits the Authorization header (the server then naturally returns 401). The handler is also exposed publicly as WebDAVClient.Authentication.BearerTokenAuthenticationHandler if you need to compose it into your own HttpClient pipeline.

Discover server capabilities (OPTIONS)

var options = await client.GetServerOptions("/dav/", cancellationToken: token);
if (!options.IsWebDavServer)
    throw new InvalidOperationException("Endpoint is not a WebDAV server");

bool supportsLock = options.IsClass2 && options.SupportsMethod("LOCK");

Lock / unlock and refresh

// Take an exclusive write lock on a file (default timeout: 600 seconds)
var info = await client.LockFile("/dav/report.docx", owner: "alice", cancellationToken: token);

// Use the lock token on subsequent writes via the If header
using (var fs = File.OpenRead(localPath))
    await client.Upload("/dav/", fs, "report.docx", lockToken: info.Token, cancellationToken: token);

// Extend / release the lock
await client.RefreshLock("/dav/report.docx", info.Token, timeoutSeconds: 600, cancellationToken: token);
await client.UnlockFile("/dav/report.docx", info.Token, cancellationToken: token);

LockInfo.Token is accepted in either bare (opaquelocktoken:abc) or <opaquelocktoken:abc> form everywhere it's used.

Set / remove custom properties (PROPPATCH)

// Set a custom dead property in your own namespace (the DAV: namespace is reserved for live properties and is rejected client-side)
await client.SetProperty("/dav/report.docx", "author", "https://example.com/ns", "Alice", token);

// Remove it later
await client.RemoveProperty("/dav/report.docx", "author", "https://example.com/ns", token);

Targeted PROPFIND — <prop> and <propname/>

// Ask only for the properties you need (saves bandwidth on large directories)
var props = new[]
{
    new PropertyName("getetag",          "DAV:"),
    new PropertyName("getcontentlength", "DAV:"),
    new PropertyName("author",           "https://example.com/ns"),
};
var items = await client.List("/dav/", depth: 1, properties: props, cancellationToken: token);

foreach (var item in items)
{
    // Standard DAV: live properties light up on Item directly (Etag, ContentLength, …)
    // Custom properties land in FoundProperties / NotFoundProperties.
    var author = item.FoundProperties?.FirstOrDefault(p => p.Name.LocalName == "author");
}

// Discover what properties a resource exposes
var names = await client.GetFilePropertyNames("/dav/report.docx", cancellationToken: token);
foreach (var n in names.AvailablePropertyNames)
    Console.WriteLine($"{n.Namespace}:{n.LocalName}");

Lock-token-aware writes (If header)

// PUT / DELETE / MOVE / COPY now accept the relevant lock tokens, so locked-resource servers stop rejecting the request with 423 Locked.
await client.DeleteFile("/dav/report.docx", lockToken: info.Token, cancellationToken: token);
await client.MoveFile("/dav/old.txt", "/dav/new.txt",
    sourceLockToken: srcToken, destinationLockToken: dstToken, cancellationToken: token);

// Opt out of clobbering an existing destination (sends Overwrite: F → server returns 412 Precondition Failed)
await client.CopyFile("/dav/a.txt", "/dav/b.txt", overwrite: false, cancellationToken: token);

Contact

You can contact me on twitter @saguiitay or on my website

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on WebDAVClient:

Package Downloads
SuperiorAcumaticaPackage

Dependencies required to compile the SuperiorAcumaticaSolution for Acumatica 2025 R2 Build 25.200.0248

IServNET

C# Api for interacting with the IServ System.

YngveHestem.Storage.WebDAV

WebDAV storage provider implementation for the YngveHestem.Storage abstractions.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on WebDAVClient:

Repository Stars
SaboZhang/EasyTidy
EasyTidy A simple file auto-classification tool makes it easy to create automatic workflows with files. / EasyTidy 一个简单的文件自动分类整理工具 轻松创建文件的自动工作流程
Version Downloads Last Updated
2.7.0 0 5/1/2026
2.5.5 0 5/1/2026
2.5.4 0 5/1/2026
2.5.3 0 5/1/2026
2.5.2 0 5/1/2026
2.5.1 0 5/1/2026
2.5.0 0 5/1/2026
2.4.0 0 5/1/2026
2.3.0 5,039 9/4/2025
2.2.1 44,698 8/25/2023
2.2.0 326 8/25/2023
2.1.0 71,296 8/25/2021
2.0.0 5,824 11/19/2020
1.1.4 8,436 6/20/2018
1.1.3 5,040 11/18/2017
1.1.2 124,080 8/8/2016
1.1.1 44,603 12/27/2015
1.1.0 1,568 12/13/2015
1.0.23 1,653 12/10/2015
1.0.21 9,383 9/2/2015
Loading failed

* Feature: WebDAV LOCK / UNLOCK support (RFC 4918 §9.10–9.11).
* Feature: WebDAV PROPPATCH support — set / remove custom properties (RFC 4918 §9.2).
* Bug fix: COPY / MOVE now send the Overwrite header (RFC 4918 §9.8.3 / §9.9.3); 204 No Content accepted as success.
* Bug fix: DELETE now sends Depth: infinity (RFC 4918 §9.6.1).
* Feature: per-call lock-token submission via the If header on PUT / DELETE / MOVE / COPY (RFC 4918 §10.4).
* Internal refactor: extracted Client.cs static helpers into focused, unit-testable helper classes under WebDAVClient.Helpers.
* Feature: PROPFIND request-body variants — <prop> and <propname/> in addition to <allprop/> (RFC 4918 §9.1).
* Feature: HTTP OPTIONS support — discover DAV compliance classes and allowed methods (RFC 4918 §9.1, RFC 9110 §9.3.7).
* Feature: Bearer token / OAuth 2.0 authentication via new Client constructor overloads (static token or async refreshable provider).