Case-Insensitive Filesystem Solutions for Linux: Handling ASP.NET Applications on Mono


3 views

When migrating ASP.NET applications from Windows to Linux using Mono, developers frequently encounter case sensitivity issues. Windows' case-insensitive filesystem often masks capitalization inconsistencies that become critical when deployed on Linux. This manifests particularly in:

  • File inclusion paths in ASPX/CSHTML files
  • Assembly references in Web.config
  • Resource file paths (images, scripts)

For developers preferring native Linux filesystems:

1. ext4 Casefold Feature (Kernel 5.2+)

Modern Linux kernels support case-insensitive lookups:


# Enable casefold on existing directory
chattr +F /var/www/myapp

# Create new casefold directory
mkdir -p /var/www/myapp
chattr +F /var/www/myapp

Note: Requires filesystem formatted with encoding=utf8 option.

2. OverlayFS with nocase Option


mount -t overlay overlay -o lowerdir=/var/www,upperdir=/var/www_upper,workdir=/var/www_work,nocase /var/www_final

Samba Share Mount (As Mentioned)


# /etc/fstab entry
//localhost/wwwshare /var/www cifs credentials=/etc/samba/creds,uid=www-data,gid=www-data 0 0

NFS with Case-Insensitive Proxy

Configure NFS server with namecase lookup:


# /etc/exports
/var/www *(rw,insecure,no_subtree_check,fsid=0,no_root_squash,crossmnt,namecase=ignore)

For environments where filesystem changes aren't possible:

Mono Runtime Configuration


<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="lib;bin" caseInsensitive="true"/>
    </assemblyBinding>
  </runtime>
</configuration>

ASP.NET Path Normalization

Add this to Global.asax.cs:


protected void Application_BeginRequest(object sender, EventArgs e)
{
    string path = Request.PhysicalPath;
    string actualPath = Directory.GetFiles(Path.GetDirectoryName(path), 
                         Path.GetFileName(path), 
                         SearchOption.TopDirectoryOnly)
                       .FirstOrDefault();
    if (actualPath != null && actualPath != path)
    {
        Context.RewritePath(actualPath);
    }
}

For Docker deployments:


FROM mono:latest
RUN apt-get update && apt-get install -y smbclient
RUN mkdir -p /mnt/www && echo "//samba/share /mnt/www cifs credentials=/samba-creds 0 0" >> /etc/fstab
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

Where entrypoint.sh contains:


#!/bin/bash
mount /mnt/www
exec mono /var/www/bin/YourApplication.exe

When migrating ASP.NET applications from Windows to Linux (using Mono or .NET Core), case sensitivity becomes a major pain point. Windows' case-insensitive filesystem allows Default.aspx and default.aspx to refer to the same file, while Linux treats them as distinct entities.

Here are the most effective approaches I've tested in production environments:

1. SMB/CIFS Mount (Most Reliable)

# /etc/fstab entry
//localhost/web_share /var/www cifs credentials=/etc/samba/creds,uid=www-data,gid=www-data,file_mode=0664,dir_mode=0775 0 0

Pros: Native Windows compatibility, easy setup
Cons: Slight performance overhead

2. Ext4 Casefold Feature (Kernel 5.2+)

# Format new partition with casefolding
mkfs.ext4 -O casefold /dev/sdX1

# Mount with proper options
mount -o casesensitive=no /dev/sdX1 /var/www

Note: Requires CONFIG_UNICODE kernel option enabled

3. OverlayFS Workaround

Create a case-insensitive layer over your existing filesystem:

mkdir -p /var/{www.upper,www.work}
mount -t overlay overlay -olowerdir=/var/www,upperdir=/var/www.upper,workdir=/var/www.work /var/www

For situations where filesystem changes aren't possible:

ASP.NET Core Middleware

app.UseStaticFiles(new StaticFileOptions {
    OnPrepareResponse = ctx => {
        var requestedPath = ctx.File.PhysicalPath;
        if (!File.Exists(requestedPath)) {
            var caseInsensitivePath = Directory.GetFiles(
                Path.GetDirectoryName(requestedPath),
                Path.GetFileName(requestedPath),
                new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
            ).FirstOrDefault();
            
            if (caseInsensitivePath != null) {
                ctx.Context.Response.Redirect($"/{Path.GetRelativePath(
                    env.WebRootPath, 
                    caseInsensitivePath
                ).Replace('\\', '/')}");
            }
        }
    }
});

Case-insensitive operations in Linux come with tradeoffs:

  • SMB: ~15-20% throughput reduction
  • Ext4 casefold: Minimal impact (~3-5%)
  • Application-level solutions: Highest overhead (30-50% for file-heavy operations)

For enterprise deployments, I recommend:

  1. Use Ext4 casefold where supported (newer kernels)
  2. Implement application-level case normalization during CI/CD pipeline
  3. For legacy systems, SMB mounts provide the best compatibility

Always test with:

find /var/www -type f | sort | xargs -I {} bash -c 'echo "${#}" "$(realpath --relative-to=/var/www "{}")"'