private readonly RequestDelegate _next;
public TrimWhitespaceMiddleware(RequestDelegate next)
_next = next;
public async Task InvokeAsync(HttpContext context)
if (HttpMethods.IsGet(context.Request.Method) || HttpMethods.IsHead(context.Request.Method))
var originalQuery = context.Request.Query;
var newQuery = originalQuery.ToDictionary(
x => x.Key,
x => x.Value.ToString().Trim()
context.Request.QueryString = QueryString.Create(newQuery);
else if (HttpMethods.IsPost(context.Request.Method) ||
HttpMethods.IsPut(context.Request.Method) ||
HttpMethods.IsDelete(context.Request.Method) ||
HttpMethods.IsPatch(context.Request.Method))
if (context.Request.HasFormContentType)
var form = await context.Request.ReadFormAsync();
context.Request.Form = new FormCollection(form
.ToDictionary(x => x.Key, x => new StringValues(x.Value.ToString().Trim())));
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8, false, 1024, true);
string bodyAsString = await reader.ReadToEndAsync();
var bodyAsJson = JObject.Parse(bodyAsString);
await RemoveSpacesFromBodyAsync(bodyAsJson);
string newBody = JsonConvert.SerializeObject(bodyAsJson, Formatting.None);
byte[] newBodyBytes = Encoding.UTF8.GetBytes(newBody);
context.Request.Body = new MemoryStream(newBodyBytes);
context.Request.ContentLength = newBodyBytes.LongLength;
context.Request.ContentType = "application/json";
await _next.Invoke(context);
private static async Task RemoveSpacesFromBodyAsync(JObject body)
foreach (var property in body.Properties())
switch (property.Value)
case JValue { Type: JTokenType.String } jValue:
property.Value = jValue.Value?.ToString()?.Trim();
break;
case JObject { } jObject:
await RemoveSpacesFromBodyAsync(jObject);
break;
case JArray { } jArray:
await foreach (var item in GetObjectsInJArray(jArray))
await RemoveSpacesFromBodyAsync(item);
break;
private static async IAsyncEnumerable
GetObjectsInJArray(JArray jArray)
foreach (var item in jArray)
if (item is JObject obj)
yield return obj;
public static class TrimRequestMiddlewareExtensions
public static IApplicationBuilder UseTrimRequest(this IApplicationBuilder builder)
return builder.UseMiddleware();