Newer
Older
Warehouse / src / Application / Common / Exceptions / InputValidationException.cs
@Derek Comartin Derek Comartin on 22 Aug 2023 1 KB Init
using FluentValidation.Results;
using System.Text.Json;

namespace MyWarehouse.Application.Common.Exceptions;

// TODO: Replace throwing exceptions for validation with an app-wide result model that contains operation result.
public class InputValidationException : Exception
{
    public IDictionary<string, string[]> Errors { get; }

    public InputValidationException(Exception? innerException = null)
        : base("One or more validation failures have occurred.", innerException)
        => Errors = new Dictionary<string, string[]>();

    public InputValidationException(params (string PropertyName, string ErrorMessage)[] failures) : this()
        => SaveGroupedErrors(failures);

    public InputValidationException(Exception? innerException, params (string PropertyName, string ErrorMessage)[] failures) : this(innerException)
        => SaveGroupedErrors(failures);

    public InputValidationException(IEnumerable<ValidationFailure> failures) : this()
        => SaveGroupedErrors(failures.Select(x => (x.PropertyName, x.ErrorMessage)));

    private void SaveGroupedErrors(IEnumerable<(string PropertyName, string ErrorMessage)> failures)
    {
        var failureGroups = failures
            .GroupBy(e => e.PropertyName, e => e.ErrorMessage);

        foreach (var failureGroup in failureGroups)
        {
            var propertyName = failureGroup.Key;
            var propertyFailures = failureGroup.ToArray();

            Errors.Add(propertyName, propertyFailures);
        }
    }

    public override string ToString()
    {
        return nameof(InputValidationException) + ": " + JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
    }
}