Skip to content

Instantly share code, notes, and snippets.

@FWest98
Created April 6, 2020 22:12
Show Gist options
  • Save FWest98/8aad0e363d68a1d49463c0f0e2a243d7 to your computer and use it in GitHub Desktop.
Save FWest98/8aad0e363d68a1d49463c0f0e2a243d7 to your computer and use it in GitHub Desktop.
.NET Core 3 Conditional Model Validation Attribute
using System;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Foo {
// Implementation makes use of the IPropertyValidationFilter interface that allows
// control over whether the attribute (and its children, if relevant) need to be
// validated.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class ConditionalValidationAttribute : Attribute, IPropertyValidationFilter {
public string OtherProperty { get; set; }
public object OtherValue { get; set; }
public ConditionalValidationAttribute(string otherProperty, object otherValue) {
OtherProperty = otherProperty;
OtherValue = otherValue;
}
public bool ShouldValidateEntry(ValidationEntry entry, ValidationEntry parentEntry) {
// Default behaviour if no other property is set: continue validation
if (string.IsNullOrWhiteSpace(OtherProperty)) return true;
// Get the property specified by the name. Might not properly work with
// nested properties.
var prop = parentEntry.Metadata.Properties[OtherProperty]?.PropertyGetter?.Invoke(parentEntry.Model);
return prop == OtherValue;
}
}
}
using System;
using System.ComponentModel.DataAnnotations;
namespace Foo {
public class Model {
public bool ShouldCheckOther { get; set; }
[Required]
[ConditionalValidation(nameof(ShouldCheckOther), true)]
public string DependentRequired { get; set; }
}
}
@benehudson
Copy link

Wanted to say thank you for making this public! This worked almost perfect. I had to tweak ShouldValidateEntry a bit.

return prop == OtherValue; didn't work for me.

switched that to return prop.Equals(OtherValue);

then i had to tweak it a smidge to handle multiple "OtherValue". Here was my solution for that...not great code, but it worked for my purposes.

return OtherValue.ToString().Contains(prop.ToString());

Final implementation looked like this: [ConditionalValidation(nameof(Reason), "event,vendor")]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment