Managing File Uploads to Windows Network Shares in ASP.NET Core

Configuration Setup

First define the necessary settings in appsettings.json:

{
 "SharedFolderSettings": {
   "RemotePath": "\\\\192.168.1.200\\Files",
   "PublicBaseUrl": "http://files.example.com/",
   "User": "shareuser",
   "Password": "sharepassword"
 }
}

Create a corresponding options class:

public class SharedFolderOptions
{
   public string RemotePath { get; set; }
   public string PublicBaseUrl { get; set; }
   public string User { get; set; }
   public string Password { get; set; }
}

Bind the configuration section in Program.cs (minimal hosting) or Startup.cs:

builder.Services.Configure<SharedFolderOptions>(
   builder.Configuration.GetSection("SharedFolderSettings"));

Establishing a Credentialed Connection

Windows shares require authentication before file operations. A disposable helper that uses the Windows Networking API (mpr.dll) is cleaner than spawning a command‑line process:

using System.Runtime.InteropServices;

public class NetworkShareConnection : IDisposable
{
   [StructLayout(LayoutKind.Sequential)]
   private class NETRESOURCE
   {
       public int dwScope;
       public int dwType;
       public int dwDisplayType;
       public int dwUsage;
       public string lpLocalName;
       public string lpRemoteName;
   }

   [DllImport("mpr.dll", CharSet = CharSet.Auto)]
   private static extern int WNetUseConnection(
       IntPtr hwndOwner,
       NETRESOURCE lpNetResource,
       string lpPassword,
       string lpUserID,
       int dwFlags,
       string lpAccessName,
       string lpBufferSize,
       string lpResult);

   [DllImport("mpr.dll", CharSet = CharSet.Auto)]
   private static extern int WNetCancelConnection2(
       string lpName,
       int dwFlags,
       bool fForce);

   private readonly string _remotePath;
   private bool _disposed;

   public NetworkShareConnection(string remotePath, string user, string password)
   {
       _remotePath = remotePath;
       var netRes = new NETRESOURCE
       {
           dwType = 1,   // RESOURCETYPE_DISK
           lpRemoteName = remotePath
       };
       int result = WNetUseConnection(IntPtr.Zero, netRes, password, user, 0, null, null, null);
       if (result != 0)
           throw new IOException($"Cannot connect to share. Error code: {result}");
   }

   public void Dispose()
   {
       if (!_disposed)
       {
           WNetCancelConnection2(_remotePath, 0, force: true);
           _disposed = true;
       }
   }
}

Streaming the Uploaded File to the Share

After a successful connection, writing the incoming file stream to the network location is straightforward:

public static class FileTransferHelper
{
   public static void SaveToShare(Stream source, string folderPath, string fileName)
   {
       if (!Directory.Exists(folderPath))
           Directory.CreateDirectory(folderPath);

       string fullPath = Path.Combine(folderPath, fileName);
       if (File.Exists(fullPath)) return; // optional: handle duplicates

       using var destination = new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
       source.CopyTo(destination);
   }
}

Controller Implementation

The file upload endpoint receives the multipart form data, generates a unique file name, opens a share connection, and stores the file. The public URL is constructed from the configured base address.

[ApiController]
[Route("api/[controller]")]
public class FilesController : ControllerBase
{
   private readonly SharedFolderOptions _settings;

   public FilesController(IOptions<SharedFolderOptions> options)
   {
       _settings = options.Value;
   }

   [HttpPost("upload")]
   public IActionResult UploadFile()
   {
       var file = Request.Form.Files.FirstOrDefault();
       if (file == null) return BadRequest("No file provided.");

       string originalName = Path.GetFileName(file.FileName);
       string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
       string storedName = $"{timestamp}_{originalName}";

       // Organize files in date‑based subdirectories
       string subFolder = DateTime.UtcNow.ToString("yyyy\\/MM\\/dd");
       string remoteDirectory = Path.Combine(_settings.RemotePath, subFolder);
       string relativePath = $"{subFolder}/{storedName}";

       try
       {
           using var connection = new NetworkShareConnection(
               _settings.RemotePath,
               _settings.User,
               _settings.Password);

           FileTransferHelper.SaveToShare(file.OpenReadStream(), remoteDirectory, storedName);

           string publicUrl = $"{_settings.PublicBaseUrl.TrimEnd('/')}/{relativePath}";
           return Ok(new { publicUrl, relativePath });
       }
       catch (Exception ex)
       {
           return StatusCode(500, $"Upload failed: {ex.Message}");
       }
   }
}

Important Considerations

  • Directory permissions: The configured Windows user must have write access to the share.
  • Thread safety: The NetworkShareConnection ties the connection to the current thread; avoid sharing it across tasks without testing.
  • Error recovery: In production, add retry logic and ensure connections are always disposed evenif exceptions occur.

Tags: ASP.NET Core Windows Share UNC Path WNetUseConnection File Upload

Posted on Wed, 02 Sep 2026 16:27:47 +0000 by CoderGoblin