Validate model before entering bank

2

I'm developing a WebAPI using EntityFramework6.

Before performing an INSERT in the database, I would like to validate the model that is coming via the request (I believe it is fundamental), but I do not have experience with good data validation practices and would like to know if EF6 provides any standard such.

I thought of making a class that will be responsible for receiving any specialization of a model, beat the data types with the model created by the Framework and if the data / size types are in agreement, returns a bool pro method that called her saying that she can continue with the insert.

The problem with this is that it would make me write a lot of code that I would only write if there was no safer, faster way to do it.

Any ideas on how to proceed?

    
asked by anonymous 09.02.2018 / 16:07

5 answers

1

I found the solution Here

The language itself provides a way to validate the model before inserting into the database via annotations using the System.ComponentModel.DataAnnotations lib in the model and using ModelState.IsValid in the method that receives the POST:

Controller:

[HttpPost]
[Route("user/")]
public HttpResponseMessage Post(user newUser)
{
    if (ModelState.IsValid)
    {
        new UserController();
        db.user.Add(newUser);
        db.SaveChanges();
        return new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(string.Format("Usuário validado e adicionado com sucesso.")),
            StatusCode = HttpStatusCode.OK,
            ReasonPhrase = "User validated and inserted successfully."
            };
        }
        else
        {
        return new HttpResponseMessage(HttpStatusCode.InternalServerError)
        {
            Content = new StringContent(string.Format("Erro na validação de dados.")),
            StatusCode = HttpStatusCode.InternalServerError,
            ReasonPhrase = "Data Validation failed."
        };
    }
}

Model:

using System.ComponentModel.DataAnnotations;

public partial class user
{
    public user()
    {
        //Código do construtor
    }

    [Key]
    [Required]
    public string id { get; set; }

    [Required]
    public string USERNAME { get; set; }

    [StringLength(8)]
    public string PASSWORD { get; set; }

    public string EMAIL { get; set; }
}
    
15.02.2018 / 14:38
1

There is a nice way to validate the model without getting too messy: Create a class called ModelStateValidationActionFilterAttribute.cs

public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid)
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
    }
}

Then in your calls just decorate the methods:

[HttpPost]
[ModelStateValidationActionFilter]
public IHttpActionResult Post(object model)
{
  // Do something here ;)
}

Below is my full article on this subject.

link

    
15.02.2018 / 15:40
0

As far as I know if you can use validation annotation normally in your viewsmodels, this will validate the request. I recommend using ModelState.IsValid on the controller to validate the model. you can also use the code below to retrieve invalid fields.

if (!ModelState.IsValid)
{
    var message = string.Join(" | ", ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage));
                throw new Exception(message);
}
    
09.02.2018 / 16:47
0

Let's do the part. When you said "model coming from the request" I assume it's a Dto, a ViewModel or any name for an object that just loads attributes. It is not interesting to use these objects as your Model or Domain entities to avoid coupling the Model layer with the Controller layer. To validate this input data, you can use Data Annotation just as Nilton did.

Now thinking that we are already talking at the domain level. It is not mandatory for the Entity Framework to do validation on this subject. The obligation is your entity. Following the object-oriented paradigm, the Customer class should validate the Client class.

I recommend you use a little recognized pattern by name, but used in quite a place, which is Good Citizen Pattern. In this pattern, your object should validate if your own state is consistent , becoming a good citizen.

There are several ways to do this, for example:

  • The constructor of a class serves much more than injecting dependency, it should be used to leave the class in a status when possible. There will be cases where only the constructor is not enough.

  • It is common (even if not specified directly in the good citizen pattern) to make a validation contract, for example IValidated. In this case, have all classes implement a validation method, so before Entity starts to play its part, you can validate the entity and, if possible, even retrieve it if necessary.

Example:

var meuNovoCliente = new Cliente(nome: "Gabriel Coletta", idade: 23);
var clienteValido = meuNovoCliente.Validar();
if(clienteValido) { 
    //chamar a camada que faz o INSERT, por exemplo;
}
    
09.02.2018 / 17:17
0

Out of the accepted response, there is still the class ValidationResult that could be used to validate your object.

var resultado = new List<ValidationResult>();
var contexto = new ValidationContext(_SeuObjeto, null, null);
Validator.TryValidateObject(_SeuObjeto, contexto, resultado, true);

You could create a project on the infrastructure to do generic object validations.

See a simple example.

    
15.02.2018 / 14:56