Mapping Validation Attributes From Domain Entity t

2019-01-21 11:02发布

I have a standard Domain Layer entity:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

which has some kind of validation attributes applied:

public class Product
{
    public int Id { get; set; }

    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

As you can see, I have made up these attributes completely. Which validation framework (NHibernate Validator, DataAnnotations, ValidationApplicationBlock, Castle Validator, etc) in use here is not important.

In my client layer, I also have a standard setup where I don't use the Domain entities themselves, but instead map them to ViewModels (aka DTO) which my view layer uses:

public class ProductViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

Let's then say that I want my client/view to be able to perform some basic property-level validations.

The only way I see I can do this is to repeat the validation definitions in the ViewModel object:

public class ProductViewModel
{
    public int Id { get; set; }

    // validation attributes copied from Domain entity
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    // validation attributes copied from Domain entity
    [NotLessThan0]
    public decimal Price { get; set;}
}

This is clearly not satisfactory, as I have now repeated business logic (property-level validation) in the ViewModel (DTO) layer.

So what can be done?

Assuming that I use an automation tool like AutoMapper to map my Domain entities to my ViewModel DTOs, wouldn't it also be cool to somehow transfer the validation logic for the mapped properties to the ViewModel as well?

The questions are:

1) Is this a good idea?

2) If so, can it be done? If not, what are the alternatives, if any?

Thank you in advance for any input!

7条回答
霸刀☆藐视天下
2楼-- · 2019-01-21 11:38

I've been considering this as well for a while now. I totally understand Brad's reply. However, let's assume I want to use another validation framework that is suitable for annotating both domain entities and view models.

The only solution I can come up with on paper that still works with attributes would be to create another attribute that "points" to a domain entity's property that you are mirroring in your view model. Here's an example:

// In UI as a view model.
public class UserRegistration {
  [ValidationDependency<Person>(x => x.FirstName)]
  public string FirstName { get; set; }

  [ValidationDependency<Person>(x => x.LastName)]
  public string LastName { get; set; }

  [ValidationDependency<Membership>(x => x.Username)]
  public string Username { get; set; }

  [ValidationDependency<Membership>(x => x.Password)]
  public string Password { get; set; }
}

A framework like xVal could possibly be extended to handle this new attribute and run the validation attributes on the dependency class' property, but with your view model's property value. I just haven't had time to flesh this out more.

Any thoughts?

查看更多
登录 后发表回答