2016年6月23日 星期四

[研究] ASP.NET MVC 5入門(十)增加驗證 (Validation)

[研究] ASP.NET MVC 5入門(十)增加驗證 (Validation)

2016-06-23

這篇是參考下面這篇的學習,不過工具從 Visual Studio 2013 改成 Visual Studio 2015 with Update 2 繁體中文版;網頁上有提到一篇新的改用 Visual Studio 2015,但是那篇要另外安裝 ASP.NET Core,而目前最新為 ASP.NET Code 1.0.0 RC2,並非正式版,所以暫時不想安裝和參考那篇。

內容不是完全翻譯,因為練習的心得,有增加、刪減圖片和文字。

Getting Started with ASP.NET MVC 5
http://www.asp.net/mvc/overview/getting-started/introduction/getting-started

請先看這篇

[研究] ASP.NET MVC 5入門(九)增加新欄位

10. Adding Validation
********************************************************************************

Keeping Things DRY ("Don't Repeat  Yourself") 

Adding Validation Rules to the Movie Model

把 Models\Movie.cs

using System;
using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
        public string Rating { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}  

修改為

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace MvcMovie.Models
{
    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; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}


(下圖) Title 欄位長度改成 3~60,實際上仍為 nvarchar(MAX),Database Schema 不會立刻變更,仍是舊的

Package Manager Console  輸入
add-migration DataAnnotations
update-database


搜尋字串 public override void Up(),找到 Migrations\201606230123369_DataAnnotations.cs

namespace MvcMovie.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
 
    public partial class DataAnnotations : DbMigration
    {
        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));
        }
     
        public override void Down()
        {
            AlterColumn("dbo.Movies", "Rating", c => c.String());
            AlterColumn("dbo.Movies", "Genre", c => c.String());
            AlterColumn("dbo.Movies", "Title", c => c.String());
        }
    }
}



Title 欄位有了最大長度限制60,但缺最小限制,要用其他辦法

Validation Error UI in ASP.NET MVC

(下圖)

How Validation Occurs in the Create View and Create Action Method

Controllers\MoviesController.cs 中 Create() 不做修改
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);
}



(下圖) 不太確定原圖的 Active scripting 是指 "允許程式碼片段",也不確定 IE 是否同版本 (本圖 IE 11)

這個設定會讓 ModelState.IsValid  為 false

(下圖) FireFox 47.0 畫面和原文圖片的也不同

Chrome v51 和原圖的還相同

Views\Movies\Create.cshtml 內容和原文不同,但仍用 Html.EditorFor 和 Html.ValidationMessageFor


@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
 
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ReleaseDate, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ReleaseDate, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ReleaseDate, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Genre, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Genre, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Genre, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Rating)
                @Html.ValidationMessageFor(model => model.Rating)
            </div>
        </div>

        <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")
}



Using DataType Attributes

System.ComponentModel.DataAnnotations namespace 提供了格式化的屬性,例如

Models\Movie.cs 內容
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
     
[DataType(DataType.Currency)]
public decimal Price { get; set; }

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

(完)

[研究] ASP.NET MVC 5入門(一)開始
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5_21.html

[研究] ASP.NET MVC 5入門(二)增加控制器(Controller)

[研究] ASP.NET MVC 5入門(三)增加檢視(View)
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5view.html

[研究] ASP.NET MVC 5入門(四)增加模型(Model)
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5model.html

[研究] ASP.NET MVC 5入門(五)建立 SQL Server LocalDB 的連線字串
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5-sql-server-localdb.html

[研究] ASP.NET MVC 5入門(六)從 Controller 存取 Model 的資料
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5-controller-model.html

[研究] ASP.NET MVC 5入門(七)瞭解 Edit Method 和 Edit View
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5-edit-method-edit-view.html

[研究] ASP.NET MVC 5入門(八)增加搜尋 Method 和 View
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5-method-view.html

[研究] ASP.NET MVC 5入門(九)增加新欄位

[研究] ASP.NET MVC 5入門(十)增加驗證 (Validation)
http://shaurong.blogspot.com/2016/06/aspnet-mvc-5-validation.html

沒有留言:

張貼留言