In this article, we will discuss how to customize the data model by using attributes that specify formatting, validation, and database mapping rules.
In Author
entity, we have BirthDate
property, and all of the web pages currently display the time along with the date.
In this field, we only need the date instead of date and time. We can use data annotation attributes and make one code change that will fix the display format in every view that shows the birth date.
In Models\Author.cs, add a using
statement for the System.ComponentModel.DataAnnotations
namespace and add DataType
and DisplayFormat
attributes to the BirthDate
property, as shown below.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace MvcWithEF6Demo.Models
{
public class Author
{
public int AuthorId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BirthDate { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
The DataType
attribute is used to specify a data type that is more specific than the database intrinsic type.
DataType.Date
does not specify the format of the date that is displayed.CultureInfo
.Let's run your application and go to the author Index
page again and you will see that times are no longer displayed for the birth dates.
The same will be true for any view that uses the Author
model.
You can also specify data validation rules and validation error messages using attributes.
StringLength
attribute sets the maximum length in the database and provides client side and server side validation for ASP.NET MVC.To add this limitation, add StringLength
attributes to the LastName
and FirstName
properties as shown below.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace MvcWithEF6Demo.Models
{
public class Author
{
public int AuthorId { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
[StringLength(20)]
public string LastName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BirthDate { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
We can also specify the ErrorMessage
which will be shown on the webpage when the user enters more than 20 characters in the name field.
[StringLength(20, ErrorMessage = "Name cannot be longer than 20 characters.")]
The database model has changed in a way that requires a change in the database schema. In the Package Manager Console
, enter the following commands.
add-migration MaxLengthOnNames
update-database
The add-migration
command creates a file named <timeStamp>_MaxLengthOnNames.cs
.
namespace MvcWithEF6Demo.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class MaxLengthOnNames : DbMigration
{
public override void Up()
{
AlterColumn("dbo.Authors", "FirstName", c => c.String(maxLength: 50));
AlterColumn("dbo.Authors", "LastName", c => c.String(maxLength: 50));
}
public override void Down()
{
AlterColumn("dbo.Authors", "LastName", c => c.String());
AlterColumn("dbo.Authors", "FirstName", c => c.String());
}
}
}
It contains the code in the Up
method that will update the database to match the current data model. The update-database
command ran that code.
The NotMapped
attribute is used to specify an entity or property is not to be mapped to a table or column in the database.
NotMapped
attribute overrides this default convention, and the entity or property will not be mapped to a table or column in the database.In the following example, the FullName
property will not be mapped to a column in the Authors
table in the database.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcWithEF6Demo.Models
{
public class Author
{
public int AuthorId { get; set; }
[StringLength(50)]
public string FirstName { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[NotMapped]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BirthDate { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
The Display
attribute specifies that the caption for the text boxes on views. For example, to show First Name, Last Name, Full Name, and Birth Date instead of the property name on the views, you can use Display
attribute.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcWithEF6Demo.Models
{
public class Author
{
public int AuthorId { get; set; }
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[NotMapped]
[Display(Name = "Full Name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime BirthDate { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
FullName
is a calculated property that returns a value by concatenating two other properties. Therefore, it has only a get accessor, and no FullName column will be generated in the database.