locked
Seeing different ways to declare a Model class and validation...which one to use? RRS feed

  • Question

  • Hi all

    I've seen examples where you simply create a model class and apply the desired Data Annotations, for instance:

     

            [Required(ErrorMessage = "First name is required.")]
            [Column("FirstName")]
            [MaxLength(50)]
            public string FirstMidName { get; set; }
    

    However I've seen other apps using a class just for validation and then using MetadataType:

     

     

    namespace NerdDinner.Models
    {
        [Bind(Include = "Title,Description,EventDate,Address,Country,ContactPhone,Latitude,Longitude")]
        [MetadataType(typeof(Dinner_Validation))]
        public partial class Dinner
        {
         ...
    
        public class Dinner_Validation
        {
            [Required(ErrorMessage = "Title is required")]
            [StringLength(50, ErrorMessage = "Title may not be longer than 50 characters")]
            public string Title { get; set; }
         ...
    

    Questions: what is the difference between MaxLength and StringLength? Is it better to use MedataType(typeof()) ?

     I also didn't undestand what Bind is used for...

    Thanks

     


    Max

    • Edited by Maximusdm Monday, October 17, 2011 7:12 PM
    Monday, October 17, 2011 7:11 PM

Answers

  • Hi Maximusdm,

    In many cases the data validation attributes are applied directly to the model class.  However, it's often a good idea to keep it in a separate "buddy" class which is a partial class (a class with the same name as the model class just with partial in front of it) just for holding the validation attributes. 

    This is not just nice for organizational purposes, it's also necessary in many cases, if the class are generated by Entity Framework then you can't modify the model class directly and put attributes on it, since your changes would be lost when the class was regenerated gain.

    Then you can even go one step further, and on your partial class for the model, specify a [MetadataType] attribute that points to yet another class that is used for purely holding metadata.  

    MaxLength and StringLength are used for two different purposes.  StringLength is used purely for validation, to specify a maximum length of a string for a particular property. 

    MaxLength on the other hand is not a validation attribute.  It's used by the Entity Framework (specifically EF 4.1) to denote how big a column is going to be on a table in the database when it gets generated from a class by the database creation logic.  If you don't specify a value then the column will be the maximum allowed by the database (varchar(max) in SQL server for example).

    The Bind(Include=...) attribute is used in MVC, to denote which properties of the class are to be included (or excluded) during an operation on your model class.   So in your example when a post occurs only those properties will be updated.  And this will be for ALL update processes on the class.  You can also define it at the ActionResult level so, for example during an Update only a specified list of properties will get updated.  

    Doing the binding is for security reasons mainly.  You don't want to open the door too wide and freely allow your MVC Controllers to be able to update every single property of your data model classes if it doesn't have to.

     

     


    Tom Overton


    • Edited by Tom_Overton Monday, October 17, 2011 11:27 PM
    • Proposed as answer by Alan_chen Tuesday, October 18, 2011 8:10 AM
    • Marked as answer by Maximusdm Tuesday, October 18, 2011 2:33 PM
    Monday, October 17, 2011 11:23 PM

All replies

  • Hi Maximusdm,

    In many cases the data validation attributes are applied directly to the model class.  However, it's often a good idea to keep it in a separate "buddy" class which is a partial class (a class with the same name as the model class just with partial in front of it) just for holding the validation attributes. 

    This is not just nice for organizational purposes, it's also necessary in many cases, if the class are generated by Entity Framework then you can't modify the model class directly and put attributes on it, since your changes would be lost when the class was regenerated gain.

    Then you can even go one step further, and on your partial class for the model, specify a [MetadataType] attribute that points to yet another class that is used for purely holding metadata.  

    MaxLength and StringLength are used for two different purposes.  StringLength is used purely for validation, to specify a maximum length of a string for a particular property. 

    MaxLength on the other hand is not a validation attribute.  It's used by the Entity Framework (specifically EF 4.1) to denote how big a column is going to be on a table in the database when it gets generated from a class by the database creation logic.  If you don't specify a value then the column will be the maximum allowed by the database (varchar(max) in SQL server for example).

    The Bind(Include=...) attribute is used in MVC, to denote which properties of the class are to be included (or excluded) during an operation on your model class.   So in your example when a post occurs only those properties will be updated.  And this will be for ALL update processes on the class.  You can also define it at the ActionResult level so, for example during an Update only a specified list of properties will get updated.  

    Doing the binding is for security reasons mainly.  You don't want to open the door too wide and freely allow your MVC Controllers to be able to update every single property of your data model classes if it doesn't have to.

     

     


    Tom Overton


    • Edited by Tom_Overton Monday, October 17, 2011 11:27 PM
    • Proposed as answer by Alan_chen Tuesday, October 18, 2011 8:10 AM
    • Marked as answer by Maximusdm Tuesday, October 18, 2011 2:33 PM
    Monday, October 17, 2011 11:23 PM
  • Thanks for the great explanation Tom!

     


    Max
    Tuesday, October 18, 2011 2:33 PM
  • To answer the main thrust of your question which Tom did not really address, why use a separate classes and the MetaDataType attribute rather than decorating your properties with validation attributes directly?

    The main reason i can see is that it is common to use Entity Framework to map your model classes to the database.  If you use database first or model first approaches with EF then your model classes are generated by EF based on your EDMX data model file, you do not code these at all.  If you modify the generated classes by adding attributes then they get wiped out next time you update the model.

    However all of the model classes are generated as partial classes so you can extend them in another file, this does not allow you to directly add attributes to the properties but it does allow you to add an attribute to the class. As such you add the MetaDataType attribute to the class to "point to" your metadata class and then you can add all your validation attributes to the metadata class without worrying about them being overwritten if you update the model.

    Wednesday, November 23, 2011 9:55 AM