Posted on 18/02/2026 13:05:32
You can do a Notifications.Frontend.OnBeforeContent notification subscriber - it is fired when a form is submitted. It is a generic notification fired when modules are executed.
In the notify, see if it is the forms module, see if it is a post, then do your validation.
Alternatively do it with middleware - GPT made me this - wrap it in ipipeline for DW10.
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using System.Net.Mime;
public sealed class FormUploadGuardMiddleware : IMiddleware
{
private readonly long _maxFileBytes = 10 * 1024 * 1024; // 10 MB
private static readonly HashSet<string> AllowedContentTypes = new(StringComparer.OrdinalIgnoreCase)
{
"image/jpeg",
"image/png",
"application/pdf"
};
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var req = context.Request;
if (!HttpMethods.IsPost(req.Method) || !req.HasFormContentType)
{
await next(context);
return;
}
// Optional: only for specific path(s)
// if (!req.Path.StartsWithSegments("/upload")) { await next(context); return; }
IFormCollection form;
try
{
// This parses application/x-www-form-urlencoded OR multipart/form-data
form = await req.ReadFormAsync(context.RequestAborted);
}
catch (InvalidDataException)
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("Invalid form data.");
return;
}
// Gate: only enforce rules when a specific field exists
if (!form.TryGetValue("specialField", out StringValues v) || StringValues.IsNullOrEmpty(v))
{
await next(context);
return;
}
foreach (var file in form.Files)
{
if (file.Length == 0)
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("Empty file not allowed.");
return;
}
if (file.Length > _maxFileBytes)
{
context.Response.StatusCode = StatusCodes.Status413PayloadTooLarge;
await context.Response.WriteAsync($"File too large (max {_maxFileBytes} bytes).");
return;
}
// Client-reported. Useful, but not trustworthy on its own.
if (!AllowedContentTypes.Contains(file.ContentType))
{
context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
await context.Response.WriteAsync($"Unsupported content type: {file.ContentType}");
return;
}
// Optional: stronger check by sniffing first bytes
// using var stream = file.OpenReadStream();
// if (!LooksLikeAllowedType(stream)) { ... }
}
await next(context);
}
}