Skip to content

Instantly share code, notes, and snippets.

@jmcd
Last active March 27, 2018 10:17
Show Gist options
  • Save jmcd/fe148052178709416b92def3a306c065 to your computer and use it in GitHub Desktop.
Save jmcd/fe148052178709416b92def3a306c065 to your computer and use it in GitHub Desktop.
ASP.NET Core Custom validation of an action parameter that is a list
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.ModelValidatorProviders.Insert(0, new ListOfFooValidatorProvider());
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc();
}
}
public class ListOfFooValidatorProvider : IModelValidatorProvider
{
public void CreateValidators(ModelValidatorProviderContext context)
{
if (typeof(IList<Foo>).IsAssignableFrom(context.ModelMetadata.ModelType))
{
context.Results.Add(new ValidatorItem()
{
Validator = new ListOfFooValidator(),
IsReusable = true
});
}
}
}
public class ListOfFooValidator : IModelValidator
{
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
{
if (!(context.Model is IList<Foo> foos)) { yield break; }
var hasDups = foos.GroupBy(f => f.Value).Any(g => g.Count() > 1);
if (hasDups)
{
yield return new ModelValidationResult(null, $"Duplicate {nameof(Foo.Value)}.{nameof(Foo.Value)} detected");
}
}
}
[Route("api/[controller]")]
public class FooController : Controller
{
[HttpPost]
public IActionResult Post([FromBody] IList<Foo> foos)
{
return !ModelState.IsValid
? (IActionResult) BadRequest(ModelState.Values.SelectMany(x => x.Errors.Select(e => e.ErrorMessage)))
: Ok();
}
}
public class Foo
{
public string Value { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment