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 (4)

Showing the top 4 NuGet packages that depend on WebDAVClient:

Package Downloads
SuperiorAcumaticaPackage

Dependencies required to compile the SuperiorAcumaticaSolution for Acumatica 2026 R1 Build 26.100.0175

CodeLogic.Storage

Provider-neutral storage abstractions and providers for CodeLogic applications

IServNET

C# Api for interacting with the IServ System.

YngveHestem.Storage.WebDAV

WebDAV storage provider implementation for the YngveHestem.Storage abstractions.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.7.0 2,456 5/1/2026
2.5.5 133 5/1/2026
2.5.4 122 5/1/2026
2.5.3 122 5/1/2026
2.5.2 121 5/1/2026
2.5.1 124 5/1/2026
2.5.0 136 5/1/2026
2.4.0 130 5/1/2026
2.3.0 10,933 9/4/2025
2.2.1 50,186 8/25/2023
2.2.0 363 8/25/2023
2.1.0 82,390 8/25/2021
2.0.0 5,873 11/19/2020
1.1.4 9,749 6/20/2018
1.1.3 5,085 11/18/2017
1.1.2 127,361 8/8/2016
1.1.1 59,004 12/27/2015
1.1.0 1,606 12/13/2015
1.0.23 1,692 12/10/2015
1.0.21 9,514 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).