0

Can I apply ModelState to an entity mapped from a DTO passed to the controller, and if not how would you apply fluent APIs to a DTO without generating a table?

To add more context to this question... I have added some fluent API validations to my entities, for example Author has an associated AuthorConfiguration class:

public class AuthorConfiguration : EntityTypeConfiguration<Author>
{
    public AuthorConfiguration()
    {

        HasKey(b => b.Id);

        Property(c => c.Name)
            .IsRequired()
            .HasMaxLength(2000);
    }
}
                

which in the AppContext class is set:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new AuthorConfiguration());
}

In the controller, I have this, however:

// POST: api/authors
public IHttpActionResult Post([FromBody] AuthorCreateDto author)
{
    var authorToInsert = Mapper.Map<Author>(author);
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    
    _unitOfWork.Authors.Add(authorToInsert);
    _unitOfWork.Complete();
    return StatusCode(HttpStatusCode.Created);
}

And the problem is that I am able to insert an author that has no name! I think this is because in the controller ModelState.IsValid would always return true as AuthorCreateDto does not have any validations. So, my questions are:

  1. how can I apply ModelState.IsValid to the authorToInsert after being mapped from Dto?
  2. Secondly, if that is not possible, and it turns I should duplicate the validations on the DTOs, similarly to the validations that I have on the domain models, another problem. I opted to have fluent API validations on domain models. If I create a configuration class similarly for the DTOs, I should inherit from : EntityTypeConfiguration and the result of this would be a new table being created in the database. So, does this mean that on DTO I cannot have fluent API validations, just data annotations?

PS. I did make it work with a Required data annotation on the DTO, but I feel this is not recommendable if the domain model has fluent API validation. It's not consistent from an overall design standpoint. Thank you.

Sami
  • 393
  • 8
  • 22
  • u need to have on your domain model. they are separate. you are correct in saying ModelState.IsValid is only validating AuthorCreateDto , with ef6 entity validation is still done by default so you would need the same validation on the entity. in efcore they drops entity validations.. well the main concept. have you googled "DTO I cannot have fluent API validations" the man issue is actually if you want to use ModelState.IsValid, as there is no piping to make fluent API validations know that it should be handles/called. – Seabizkit Jul 10 '20 at 10:25
  • i would say put the validations on the entities... as primary and dto as secondary until you work out how you want to handle this. – Seabizkit Jul 10 '20 at 10:28
  • Hi Seabizkit, thank you. I did search and found things like "The workflow for POST will be: -> DTO comes in -> Swap dto to Model -> Validate the model -> Swap model to entity -> Store entity in database -> Use the updated entity and swap it to a new dto -> Return the dto" but I don't get it. How should I SWAP? And I did try to MAP the domain object from the DTO (if that counts as a SWAP?) - Nonetheless, it doesn't work. ModelState still considers the DTO passed to the controller. – Sami Jul 10 '20 at 10:42
  • I didn't find any example anywhere. – Sami Jul 10 '20 at 10:42
  • then probably not a simple task. several ways to skin a cat but this should give an option https://www.c-sharpcorner.com/article/updatemodel-and-tryupdatemodel-in-asp-net-mvc/ see section where they use TryUpdateModel(employee); – Seabizkit Jul 10 '20 at 10:50

0 Answers0