Skip to content

Instantly share code, notes, and snippets.

@stand-sure
Created July 8, 2022 22:35
Show Gist options
  • Save stand-sure/d49fa33ea92e4be5937a388121485011 to your computer and use it in GitHub Desktop.
Save stand-sure/d49fa33ea92e4be5937a388121485011 to your computer and use it in GitHub Desktop.
C# trim string binder (MVC)
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Options;
public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
private readonly IHttpRequestStreamReaderFactory readerFactory;
public ConfigureMvcOptions(IHttpRequestStreamReaderFactory readerFactory)
{
this.readerFactory = readerFactory;
}
public void Configure(MvcOptions options)
{
options.ModelBinderProviders.Insert(0, new TrimStringsBinderProvider(options.InputFormatters, this.readerFactory));
}
}
// ...
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
// ...
}
// ...
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
public class TrimStringsBinder : IModelBinder
{
private readonly BodyModelBinder bodyModelBinder;
public TrimStringsBinder(IList<IInputFormatter> formatters, IHttpRequestStreamReaderFactory readerFactory)
{
this.bodyModelBinder = new BodyModelBinder(formatters, readerFactory);
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
await this.bodyModelBinder.BindModelAsync(bindingContext).ConfigureAwait(false);
if (bindingContext.Result.IsModelSet && bindingContext.Result.Model != null)
{
object model = bindingContext.Result.Model;
IEnumerable<PropertyInfo> stringProperties = model.GetType().GetProperties()
.Where(info => info.PropertyType == typeof(string) && !info.GetCustomAttributes<DoNotTrimAttribute>().Any()).ToList();
foreach (PropertyInfo stringProperty in stringProperties)
{
try
{
string? value = (stringProperty.GetValue(model) as string)?.Trim();
stringProperty.SetValue(model, value);
}
catch (Exception)
{
// swallow
}
}
}
}
}
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
public class TrimStringsBinderProvider : IModelBinderProvider
{
private readonly BodyModelBinderProvider bodyModelBinderProvider;
private readonly IList<IInputFormatter> formatters;
private readonly IHttpRequestStreamReaderFactory readerFactory;
public TrimStringsBinderProvider(IList<IInputFormatter> formatters, IHttpRequestStreamReaderFactory readerFactory)
{
this.formatters = formatters;
this.readerFactory = readerFactory;
this.bodyModelBinderProvider = new BodyModelBinderProvider(formatters, readerFactory);
}
public IModelBinder? GetBinder(ModelBinderProviderContext context)
{
IModelBinder? modelBinder = this.bodyModelBinderProvider.GetBinder(context);
if (modelBinder != null)
{
modelBinder = new TrimStringsBinder(this.formatters, this.readerFactory);
}
return modelBinder;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment