When using Data Annotations with MVC, Pro and Cons

2019-02-04 20:13发布

If you read this article on Validation with the Data Annotation Validators, it shows that you can use the MetadataType attribute to add validation attributes to properties on partial classes. You use this when working with ORMs like LINQ to SQL, Entity Framework, or Subsonic. Then you can use the "automagic" client and server side validation. It plays very nicely with MVC.

However, a colleague of mine used an interface to accomplish exactly the same result. it looks almost exactly the same, and functionally accomplishes the same thing. So instead of doing this:

[MetadataType(typeof(MovieMetaData))]
public partial class Movie
{
}

public class MovieMetaData
{
    [Required]
    public object Title { get; set; }

    [Required]
    [StringLength(5)]
    public object Director { get; set; }


    [DisplayName("Date Released")]
    [Required]
    public object DateReleased { get; set; }
}

He did this:

public partial class Movie :IMovie
{
}

public interface IMovie
{
    [Required]
    object Title { get; set; }

    [Required]
    [StringLength(5)]
    object Director { get; set; }


    [DisplayName("Date Released")]
    [Required]
    object DateReleased { get; set; }
}

So my question is, when does this difference actually matter?

My thoughts are that interfaces tend to be more "reusable", and that making one for just a single class doesn't make that much sense. You could also argue that you could design your classes and interfaces in a way that allows you to use interfaces on multiple objects, but I feel like that is trying to fit your models into something else, when they should really stand on their own. What do you think?

3条回答
虎瘦雄心在
2楼-- · 2019-02-04 20:50

If those two options are the two I am presented with, I would personally probably choose the interface way, simply because I think it looks cleaner. But this is entirely based on personal taste - I don't know enough about the inner workings of .NET to say for sure, but I don't know any case where the actual functionality of the two approaches would differ.

On the other hand, a much better approach would be to use Data Transfer Objects (DTO's) for sending data back and forth, and have the validation requirements on them. That is, instead of requiring that the Movie object meet all the validation requirements, you require that a MovieInput object meets all those requirements, and then create code to map a correct MovieInput into a Movie. (If you don't want to do that manually, you could use AutoMapper or some other utility).

The concept is basically to have something like a View Model object on the way in just as well as on the way out - I could just as well have let MovieInput be called MovieViewModel and use it for transferring of data both in and out of the server.

查看更多
甜甜的少女心
3楼-- · 2019-02-04 20:59

I like your interface approach as it allows you to define a contract for your model which you can use to adapt your ORM generated classes to. That would allow you to decouple your app from the ORM framework and get more use out of the MetadataType interface as it serves as data validation metadata as well as a contract for your model. You could also decorate your interface with serialization attributes for use in WCF gaining more use out of the interface. I followed a few early blogs that recommended creating a metadata class but again I think the interface solution is a nice idea.

查看更多
趁早两清
4楼-- · 2019-02-04 21:05

I see no functional difference between the two approaches. I'm not sure reusability is really important here, given that validation will most often be on "one-off" ViewModels that probably won't get much, if any, reuse.

查看更多
登录 后发表回答