Last active
July 17, 2020 22:01
-
-
Save azborgonovo/51366fe5d9741fcf1e1d to your computer and use it in GitHub Desktop.
Validation in C# with System.ComponentModel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IObjectValidator<T> | |
{ | |
IEnumerable<ValidationResult> Validate(T @object); | |
} | |
public bool Validate(T objeto, out ICollection<ValidationResult> results) | |
{ | |
var validationResults = new List<ValidationResult>(); | |
// Default validation | |
var context = new ValidationContext(objeto, serviceProvider: null, items: null); | |
bool selfValidationFailed = !Validator.TryValidateObject(objeto, context, validationResults, validateAllProperties: true); | |
// Object validators | |
var validators = ServiceLocator.Current.GetAllInstances<IObjectValidator<T>>(); | |
foreach (var validator in validators) | |
{ | |
var validatorResults = validator.Validate(objeto); | |
foreach (var item in validatorResults) | |
validationResults.Add(item); | |
} | |
results = validationResults; | |
return results.Count > 0; | |
} | |
public void Validate<T>(T item) | |
{ | |
ICollection<ValidationResult> results; | |
if (!Validate(item, out results)) | |
throw new ValidationErrorsException(results); | |
} | |
public class SomeEntityValidation : IObjectValidator<SomeEntity> | |
{ | |
readonly ISomeRepository _repository; | |
public SomeEntityValidation(ISomeRepository repository) | |
{ | |
_repository = repository; | |
} | |
public IEnumerable<ValidationResult> Validate(SomeEntity entity) | |
{ | |
// TODO: global validation rules here | |
} | |
} | |
[Serializable] | |
public class ValidationErrorsException : Exception | |
{ | |
IEnumerable<ValidationResult> ValidationResults { get; set; } | |
public ValidationErrorsException() | |
{ | |
} | |
public ValidationErrorsException(IEnumerable<ValidationResult> validationResults) | |
{ | |
ValidationResults = validationResults; | |
} | |
public ValidationErrorsException(string message) : base(message) | |
{ | |
} | |
public ValidationErrorsException(string message, Exception innerException) : base(message, innerException) | |
{ | |
} | |
protected ValidationErrorsException(SerializationInfo info, StreamingContext context) : base(info, context) | |
{ | |
} | |
} | |
// WebAPI exception handler | |
public class CustomExceptionHandler : ExceptionHandler | |
{ | |
public override void Handle(ExceptionHandlerContext context) | |
{ | |
var exception = context.Exception as ValidationErrorsException; | |
if (exception != null) | |
{ | |
var modelState = new ModelStateDictionary(); | |
foreach (var validationResult in exception.ValidationResults) | |
{ | |
foreach (var memberName in validationResult.MemberNames) | |
{ | |
modelState.AddModelError(memberName, validationResult.ErrorMessage); | |
} | |
} | |
context.Result = new InvalidModelStateResult( | |
modelState, | |
true, | |
new DefaultContentNegotiator(), | |
context.Request, | |
new MediaTypeFormatter[] { new JsonMediaTypeFormatter() } | |
); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment