Validate model before inserting in the database

Asked

Viewed 371 times

2

I am developing a Webapi using Entityframework6.

Before performing an INSERT in the database, I would like to validate the model that is coming via request (I believe to be fundamental), but I have no experience in the good practices of data validation and would like to know if EF6 provides any standard resource for this.

I thought of making a class that will be responsible for receiving any specialization from a model, beat the data types with the model created by the Framework and if the data types/size are in accordance, returns a bool for the method that called it saying it can follow with the Insert.

The problem with that is that it would make me write a lot of code that I would only write if there wasn’t a safer and faster way to do it.

Any idea how to follow?

  • Would validating what you say be something like, for example, a field that does not accept negative values? If it is the obligation to do so, it becomes your domain.

  • @Gabrielcoletta would like to, for example, receive a model of the client type and validate if this model has all the mandatory data of the database table, besides validating if the username has no space, if the password meets the criteria, etc.

  • 1

    @Csorgo takes a look at my answer, it will be nicer yet your example, and you do not need to be doing if throughout post.

5 answers

1

There is a nice way to validate the model without getting too dirty the code: 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);
    }
}

There in your calls just memorize the methods:

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

Below is my full article on this subject.

https://medium.com/@thiagoloureiro/validating-models-em-webapis-e2471949b49c

  • 1

    Great guy, it will be very useful in my application! Thanks for the tip!

1


I found the solution Here

The language itself provides a way to validate the model before inserting it into the database via Annotations using lib System.ComponentModel.DataAnnotations on 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; }
}

0

As far as I know if you can use the validation Annotation normally in your viewsmodels, with this you will perform the validation in the request. I advise the use of ModelState.IsValid in the controller to validate the model. you can also use the code below to recover the fields with invalid.

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

0

Let’s go by part. When you said "model that comes from the request" I assume it is a Dto, a Viewmodel or any name for an object that only carries 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 like Nilton said.

Now thinking that we are already talking about the domain level. It is not the obligation of the Entity Framework to validate this subject. The obligation is of your entity. Following the object orientation paradigm, who must validate the Client class is the Client itself.

I recommend you use a pattern little recognized by name, but used quite a lot, which is the Good Citizen Pattern. In this pattern, your object must validate whether your own state is consistent, becoming a good citizen.

There are several ways to do this, for example:

  • The manufacturer of a class serves much more than injecting dependency, it should be used to leave the class in a valid state whenever possible. There will be cases where only the manufacturer is not sufficient.

  • It is common (even if it is not specified directly in 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 playing its role, you can validate the entity and, if possible, even retrieve it if needed.

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;
}
  • Well, then, I think I’d better make an exception in the construction of the object? this exception could be handled in the controler to return a message, or status code if an http request pro client.

  • In the case Data Annotation in the Controller layer would do this, as Nilton represented and I reaffirmed the effectiveness. However, validating the domain only in the input of some attributes is flawed, since I can modify my object in another layer.

  • i don’t know C#, but for example in java, I can prevent the state from being changed without going through validations, excluding getters and setters, ie not having Dumb classes, I could do this in C#?

  • Yes, as in java, in C# we have the same accessors, but they are engaged directly in the field, called properties. Because of this the getters and setters always exist, but I can leave them private or create a readonly variable, or even create it immutable (see implementation).

0

Apart from the accepted answer, 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 an infrastructure project to do generic object validations.

See a simple example.

Browser other questions tagged

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