asp.net MVC 5-Adding a validator to the data model

Source: Internet
Author: User
Tags bind border color datetime http post locale table definition visual studio
In this section you will add validation logic to the Movie model. And make sure these validation rules are enforced when users create or edit movies.

Refuse to repeat DRY
One of the core design tenets of ASP.NET MVC is DRY: "DRY-Don't Repeat Yourself". ASP.NET MVC encourages you to specify a feature or behavior, do it once, and then apply it everywhere in your application. This reduces the amount of code you need to write, reduces code error rates, and makes code maintenance easier.

Providing validation support for ASP.NET MVC and Entity Framework Code First is a great practice for the DRY creed. You can specify validation rules declaratively in one place (model class), and this rule will be executed anywhere in the application.

Let's see how you can use this verification support in this movie application.

Adding validation rules to movie models
You will first add some validation logic to the Movie class.

Open the Movie.cs file and notice that the System.Web namespace does not include System.ComponentModel.DataAnnotations. DataAnnotations provides a set of built-in serious properties that you can apply to classes and properties. (DataAnnotations also contains a DataType property to help format the way to verify)

Update the Movie class to take advantage of the built-in Required, StringLength, RegularExpression, and Range validation properties. Take the following code as an example to apply validation attributes.

Copy code
public class Movie

{

public int ID {get; set;}

[StringLength (60, MinimumLength = 3)]

public string Title {get; set;}

[Display (Name = "Release Date")]

[DataType (DataType.Date)]

[DisplayFormat (DataFormatString = "{0: yyyy-MM-dd}", ApplyFormatInEditMode = true)]

public DateTime ReleaseDate {get; set;}

[RegularExpression (@ "^ [A-Z] + [a-zA-Z ''-'\ s] * $")]

[Required]

[StringLength (30)]

public string Genre {get; set;}

[Range (1, 100)]

[DataType (DataType.Currency)]

public decimal Price {get; set;}

[RegularExpression (@ "^ [A-Z] + [a-zA-Z ''-'\ s] * $")]

[StringLength (5)]

public string Rating {get; set;}

}
Copy code
 

Set the maximum length of the string in the StringLength property, it will set this limit on the database, so the database schema will change. Right-click the movie table, in Server explorer, and click Open Table Definition:

clip_image002

In the picture above, you can see that all string fields are set to the NVARCHAR (MAX) data type. We will use migrations to update the schema. Build the solution, then open the Package Manager Console and enter the following command:

add-migration DataAnnotations
update-database

When this command is completed, Visual Studio will open the class code file, which defines a new DbMIgration derived class (DataAnnotations). You can see the updated schema constraint code in the Up method as follows:

Copy code
public override void Up ()

{

AlterColumn ("dbo.Movies", "Title", c => c.String (maxLength: 60));

AlterColumn ("dbo.Movies", "Genre", c => c.String (nullable: false, maxLength: 30));

AlterColumn ("dbo.Movies", "Rating", c => c.String (maxLength: 5));

}
Copy code
 

The Genre field is no longer Null (that is, you must enter a value). The maximum length of the Rating field is 5 and the maximum length of the title is 60. The minimum length of the title and price ranges has not changed.

Please check the schema of the movie table in the database:

clip_image004

This string field shows the new length limit and the genre field (Genre) can no longer be empty.

Validation attributes indicate the behavior you want to apply to the model attributes. The Required and MinimummLength attributes indicate that an attribute cannot be null, but nothing prevents the user from entering a space to verify. The RegularExpression property is used to restrict which characters can be entered. In the code above, Genre and Rating can only use letters (spaces, numbers, and special characters are not allowed). The value of the Range property constraint is within a specified range. The StringLength property allows you to set the maximum length of a string property, as well as the minimum length (optional). Value types (decimal, int, float, DateTime) have inherent required settings and do not require the Required property.

Code First ensures that your model stores changes in the database on the specified class before validation rules are enforced. For example, the following code will throw a DbEntityValidationException when calling the SaveChanges method because several necessary Movie properties are missing:

Copy code
MovieDBContext db = new MovieDBContext ();

Movie movie = new Movie ();

movie.Title = "Gone with the Wind";

db.Movies.Add (movie);

db.SaveChanges (); // <= Will throw server side validation exception
Copy code
 

The above code will throw the following exception:

Validation failed for one or more entities. See the 'EntityValidationErrors' property for more information.

Having validation rules that are automatically enforced through the .NET Framework can help make your applications more robust. It also ensures that you can't forget what you verify, that is, you don't inadvertently write bad data to the database.

ASP.NET MVC validation error UI
Re-run the application and browse to the URL of / Movies.

Click the Create New link to add a new movie. Fill in some invalid values in the form and click the Create button.

Like jQuery's client-side validation to detect errors, it displays an error message.



Note that in order for jQuery to support authentication in non-English locales using commas, you need to set a comma (",") to represent the decimal point, as described earlier in this tutorial, you must introduce NuGet globalize. Note that the form has automatically highlighted the text box with a red border color next to each corresponding validation error message to indicate invalid data. These errors are enforced on the client side (using JavaScript and jQuery) and on the server side (if JavaScript is disabled by the user).

A real benefit is that you don't need to change a single line of code in the MoviesController class or the Create.cshtml view to enable this validated user interface. The controllers and views you created in the previous tutorial are automatically enabled, using the properties of the Movie model class specified by validation. Using the Edit behavior method, the same verification method is fully applicable. The form data will not be sent back to the server until there are any client-side validation errors. You can verify this by using a breakpoint in the HTTP POST method; or by using the fiddler tool, or the Internet Explorer F12 developer tools.

How to verify the creation view and creation method
You might be wondering how the validation user interface is generated without updating the controller or view code. The Create method in the MovieController class is listed below. They were generated automatically in the previous tutorial and have not been modified.

Copy code
public ActionResult Create ()

{

return View ();

}

// POST: / Movies / Create

// To protect from overposting attacks, please enable the specific properties you want to bind to, for

// more details see http://go.microsoft.com/fwlink/?LinkId=317598.

[HttpPost]

[ValidateAntiForgeryToken]

public ActionResult Create ([Bind (Include = "ID, Title, ReleaseDate, Genre, Price, Rating")] Movie movie)

{

if (ModelState.IsValid)

{

        db.Movies.Add (movie);

        db.SaveChanges ();

return RedirectToAction ("Index");

}

return View (movie);

}
Copy code
 

The first (HTTP GET) Create method is used to display the initial creation form. The second ([HttpPost]) method handles the request for the form. The second Create method (HttpPost version) calls ModelState.IsValid to check if there are any Movie validation errors. Calling this method will validate all attributes on the object with validation constraints applied. If the object contains validation errors, the Create method will redisplay the original form. If there are no errors, the method saves the information to the database. In our movie example, we used validation. When the client detects an error, the form is not posted to the server; so the second Create method is never called. If you disable JavaScript in your browser, client-side validation is also disabled, and the HTTP POST Create method calls ModelState.IsValid to check if the movie contains any validation errors.

You can set a breakpoint in the HttpPost Create method. When client-side validation detects an error, the form data is not posted, so this method is never called. If you disable JavaScript in your browser and then submit a form with an error message, the breakpoint will hit. You are still fully validated, even without JavaScript.

The following figure shows how to disable JavaScript in Internet Explorer.

clip_image008

clip_image010

The following figure shows how to disable JavaScript in Firefox.

clip_image012

The following figure shows how to disable JavaScript in Chrome.

clip_image014

Here is the Create.cshtml view template generated by the framework code in the previous tutorial. It is used to display the initial form for the above two operation methods, and to redisplay the view when validation errors occur.

Copy code
@model MvcMovie.Models.Movie

@ {

    ViewBag.Title = "Create";

}

<h2> Create </ h2>

@us
ing (Html.BeginForm ())

{

    @ Html.AntiForgeryToken ()

<div class = "form-horizontal">

<h4> Movie </ h4>

<hr />

        @ Html.ValidationSummary (true)

<div class = "form-group">

            @ Html.LabelFor (model => model.Title, new {@class = "control-label col-md-2"})

<div class = "col-md-10">

                @ Html.EditorFor (model => model.Title)

                @ Html.ValidationMessageFor (model => model.Title)

</ div>

</ div>

        @ * Fields removed for brevity. * @

<div class = "form-group">

<div class = "col-md-offset-2 col-md-10">

<input type = "submit" value = "Create" class = "btn btn-default" />

</ div>

</ div>

</ div>

}

<div>

    @ Html.ActionLink ("Back to List", "Index")

</ div>

@section Scripts {

    @ Scripts.Render ("~ / bundles / jqueryval")

}
Copy code
 

Note how the code uses the Html.EditorFor helper to output the <input> element for each attribute in the Movie. Next to this helper is a call to the Html.ValidationMessageFor method. These two helper methods will handle the model object (in this case, the Movie object) passed by the controller to the view. They automatically find the validation attributes specified in the model and display the appropriate error message.

If you want to change the validation logic later, you can do it in one place and add the validation information to the model. (In this example, the movie class). You don't have to worry about non-compliance, validation logic will be executed in different parts of the application-defining validation logic in one place will be used everywhere. This makes the code very clean and makes it easy to maintain and extend. It means that you will fully adhere to the DRY principle.

Using the DataType property
Open the Movie.cs file and check the Movie class. The formatting properties provided in the System.ComponentModel.DataAnnotations namespace, in addition to the built-in set of validation properties. We have applied the ReleaseDate and Price fields of the DataType enumeration value. The following code shows ReleaseDate and Price with the appropriate DataType properties.

[DataType (DataType.Date)]

public DateTime ReleaseDate {get; set;}

[DataType (DataType.Currency)]

public decimal Price {get; set;}

The DataType property only provides a hint to the view engine to format the data (with corresponding properties, such as <a> replaced by URL and <a href="mailto:EmailAddress.com"> instead of email. You can use the properties of RegularExpression To validate the data format. The DataType attribute is used to specify a data type that is more specific than the internal database type, but they are not validation attributes. In this case, we only need to keep the date tracking, not the date and time. The enumerated DataType provides multiple data types, such as Date, Time, PhoneNumber, Currency, EmailAddress, and many more. The properties of the DataType can also enable applications to automatically provide specific types of functionality. For example, a mailto: The link can be created with DataType.EmailAddress and the date picker can be provided in the DataType.Date provided by browsers that support HTML5. This data type attribute is emitted by the HTML5data- (pronounced pronunciation data dash) attribute that can be understood by HTML5 browsers. The DataType attribute does Provide any verification.

DataType.Date does not specify the date format to be displayed. By default, data fields are displayed according to a server-based CultureInfo preset format.

The DisplayFormat property is used to explicitly specify the date format:

[DisplayFormat (DataFormatString = "{0: yyyy-MM-dd}", ApplyFormatInEditMode = true)]

public DateTime EnrollmentDate {get; set;}

The ApplyFormatInEditMode setting specifies that when the value is edited in a text box, formatting should also apply. (You may not want certain fields like this-such as currency values, you may not want currency symbols to appear in the edit text box.)

You can use the DisplayFormat property alone; but with the DataType property, it is usually a good idea. The DataType property passes the semantics of the data instead of how it is rendered on the screen and has the following advantages without DisplayFormat:

Browsers can enable HTML5 features (such as displaying a calendar control, setting the corresponding currency symbol in the locale, links in emails, etc.).

· By default, the browser renders the data in the correct locale-based format.

The DataType attribute allows MVC to choose the appropriate field template to render the data (if the DisplayFormat itself is using a string template) For more information, see Brad Wilson's ASP.NET MVC 2 Templates. (While writing MVC2, this article still applies to the current version of ASP.NET MVC 5.)

If you are using a DataType property with a date field, you must also specify to ensure that the field renders the DisplayFormat property in Chrome correctly. For more information, see this StackOverflow thread.

Note: jQuery's validation does not work with both the Range property and DateTime. For example, the following code always shows a client-side validation error, even when the date is within the specified range:

[Range (typeof (DateTime), "1/1/1966", "1/1/2020")]

You might disable jQuery's date validation and use DateTime with the Range property. This is usually not a good practice. In your model, it is difficult for the compiler to determine the date, so using the Range property and DateTime does not work well.

The following code shows merge properties on the same line:

Copy code
public class Movie

{

public int ID {get; set;}

[Required, StringLength (60, MinimumLength = 3)]

public string Title {get; set;}

[Display (Name = "Release Date"), DataType (DataType.Date)]

public DateTime ReleaseDate {get; set;}

[Required]

public string Genre {get; set;}

[Range (1, 100), DataType (DataType.Currency)]

public decimal Price {get; set;}

[Required, StringLength (5)]

public string Rating {get; set;}

}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.