How to fire multiple errors in a single data check using C#

Asked

Viewed 58 times

1

I am creating a solution where I would like to keep all business rules within my models including the answer to errors. The problem is that I would also like to be able to capture multiple errors at once like this:

public class Usuario
{
    private int idade;
    public int Idade
    {
        get => idade;
        set
        {
            if (value < 18)
                throw new ArgumentOutOfRangeException("O usuário precisa ter mais que 18 anos.");

            idade = value;
        }
    }

    private string senha;
    public string Senha
    {
        get => senha;
        set
        {
            if (string.IsNullOrWhiteSpace(value) || value.Length < 6 || value.Length > 50)
                throw new ArgumentException("A senha deve ter entre 6 e 50 caracteres.");
            senha = value;
        }
    }
}

I need that when making a new instance of this user and feeding this information, I can return all errors related to the implementation of the model so that, these can be used to inform the user of the model (which may be an API, a view, or any other), like:

public class PropertySetError
{
    public string Name { get; set; }
    public ICollection<string> Errors { get; set; }
}

public class Response<T>
{
    public bool Status { get; set; }
    public ICollection<PropertySetError> InvalidProperties { get; set; }
}

public class UsuarioController : ControllerBase
{
    [HttpPost("/usuario")]
    public async Task<ActionResult<Response<Usuario>>> postUsuario([FromBody] JObject obj)
    {
        Usuario usuario = new Usuario();
        object temp = null;
        Response<Usuario> response = new Response<Usuario>();

        try
        {
            foreach(var prop in typeof(Usuario).GetProperties())
            {
                try
                {
                    obj.TryGetValue(prop.Name, out temp);
                    prop.SetValue(usuario, Convert.ChangeType(temp, prop.GetType()));
                }
                catch (Exception)
                {
                    throw;
                }
            }

            response.Status = true;
            return response;
        }
        catch (Exception ex)
        {
            response.Status = false;

            // ... pega todos os possíveis erros aqui e passa para a resposta

            return response;
        }
    }
}

1 answer

2


try {
    obj.TryGetValue(prop.Name, out temp);
    prop.SetValue(usuario, Convert.ChangeType(temp, prop.GetType()));
}
catch (Exception) {
    throw;
}

I put in the Github for future reference.

This makes no sense, capturing an exception just to launch it again is something wrong. If you have nothing useful to do with the exception do not capture it. The other catch is actually correct, but avoid capturing Exception, almost always this is a mistake.

Before using exception I would study more its use. There are many things here on the site. People abuse to create launch and mainly capture exceptions, in this case certainly.

I’m not a fan of making an exception in these cases, but being a property makes it difficult to validate otherwise. And I hope it’s just a bad example, outside the track was not made for what was used, there is an argument error too.

The fact of wanting to take several exceptions is already indicative that this is not the correct mechanism.

But maybe, and just maybe, you might want to use the AggregateException.

I also consider the use of reflection in this case exaggerated, you should have this information at compile time, it is much easier, robust and fast to use them, even if you have to type something else.

  • got it, good idea is that I can use the model classes anywhere and centralize all the business rules in them but, also be able to validate everything at once instead of calling one error at a time.

  • now that I read more about Aggregateexception really that’s what I was looking for!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.