.NET Core第30天_Model驗證配置準備流程_各種驗證資料註解使用方式_part2(Remote,DataType,EmailAddress,Display,DisplayFormat驗證)
Remote
可用來實踐利用Server-Side的 call back函數執行client-side驗證。
用法[Remote("動作方法名","隸屬控制器名")],其隸屬於Microsoft.AspNetCore.Mvc該命名空間。
RemoteAttribute.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #region 組件 Microsoft.AspNetCore.Mvc.ViewFeatures, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 // C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\5.0.0\ref\net5.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll #endregion using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using System; namespace Microsoft.AspNetCore.Mvc { // // 摘要: // A Microsoft.AspNetCore.Mvc.RemoteAttributeBase for controllers which configures // Unobtrusive validation to send an Ajax request to the web site. The invoked action // should return JSON indicating whether the value is valid. // // 備註: // Does no server-side validation of the final form submission. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class RemoteAttribute : RemoteAttributeBase { // // 摘要: // Initializes a new instance of the Microsoft.AspNetCore.Mvc.RemoteAttribute class. // // 參數: // routeName: // The route name used when generating the URL where client should send a validation // request. // // 備註: // Finds the routeName in any area of the application. public RemoteAttribute(string routeName); // // 摘要: // Initializes a new instance of the Microsoft.AspNetCore.Mvc.RemoteAttribute class. // // 參數: // action: // The action name used when generating the URL where client should send a validation // request. // // controller: // The controller name used when generating the URL where client should send a validation // request. // // 備註: // If either action or controller is null, uses the corresponding ambient value. // Finds the controller in the current area. public RemoteAttribute(string action, string controller); // // 摘要: // Initializes a new instance of the Microsoft.AspNetCore.Mvc.RemoteAttribute class. // // 參數: // action: // The action name used when generating the URL where client should send a validation // request. // // controller: // The controller name used when generating the URL where client should send a validation // request. // // areaName: // The name of the area containing the controller. // // 備註: // If either action or controller is null, uses the corresponding ambient value. // If areaName is null, finds the controller in the root area. Use the Microsoft.AspNetCore.Mvc.RemoteAttribute.#ctor(System.String,System.String) // overload find the controller in the current area. Or explicitly pass the current // area's name as the areaName argument to this overload. public RemoteAttribute(string action, string controller, string areaName); // // 摘要: // Initializes a new instance of the Microsoft.AspNetCore.Mvc.RemoteAttribute class. // // 備註: // Intended for subclasses that support URL generation with no route, action, or // controller names. protected RemoteAttribute(); // // 摘要: // Gets or sets the route name used when generating the URL where client should // send a validation request. protected string RouteName { get; set; } protected override string GetUrl(ClientModelValidationContext context); } } |
新建好RemoteController跟相應Index檢視
RemoteController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Controllers { public class RemoteController : Controller { public IActionResult Index() { return View(); } /// <summary> /// Call Back Function for Remote Validation /// </summary> /// <param name="name"></param> /// <param name="age"></param> /// <returns></returns> public JsonResult CheckName(string name) { bool b = false; if (name.Equals("Andy")) { b = true; } return Json(b); } } } |
Index.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @{ ViewData["Title"] = "Remote驗證"; } @model RemoteViewModel <form> <div> <label asp-for="Name"></label> <input type="text" asp-for="Name" /> <span asp-validation-for="Name"></span> </div> <div> <label asp-for="Age"></label> <input type="text" asp-for="Age" /> <span asp-validation-for="Age"></span> </div> <div> <input type="submit" value="提交" /> </div> </form> @section scripts{ @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} } |
RemoteViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class RemoteViewModel { [Display(Name = "姓名")] [Remote("CheckName", "Remote")] public string Name { get; set; } [Display(Name = "年齡")] public int Age { get; set; } } } |
這裡可以觀察運行結果
當輸入一個隨意的名稱時會自動到server-side我們指定的call back函數做驗證
當改為Andy時才消失警示(這裡判斷是大小寫有差)
AdditionalFields屬性於Remote下可以在多透過設置它來附加額外要驗證的參數欄位。
使call back函數可以傳進更多參數
微調後的RemoteViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class RemoteViewModel { [Display(Name = "姓名")] [Remote("CheckName", "Remote", AdditionalFields = "Age", HttpMethod = "GET", ErrorMessage = "請輸入正確的內容。")] public string Name { get; set; } [Display(Name = "年齡")] public int Age { get; set; } } } |
這裡還可以透過HttpMethod設置要採用POST或GET(默認)
AdditionalFields 當有多個參數則可用逗號分隔。
微調後的RemoteController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Controllers { public class RemoteController : Controller { public IActionResult Index() { return View(); } /// <summary> /// Call Back Function for Remote Validation /// </summary> /// <param name="name"></param> /// <param name="age"></param> /// <returns></returns> public JsonResult CheckName(string name,int age) { bool b = false; if (name.Equals("Andy") && age > 30) { b = true; } return Json(b); } } } |
運行效果
DataType
用於設定使用顯示/編輯模板呈現的模型物件屬性轉換的HTML控件類型。
以下這些enum選項都可以對應HTML呈現
新建好DataTypeController跟相應Index檢視
Index.cshtml
1 2 3 4 5 6 7 8 | @{ ViewData["Title"] = "DataType "; } @model DataTypeViewModel <div> <input asp-for="Title" /> </div> |
DataTypeViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DataTypeViewModel { [DataType(DataType.DateTime)] public string Title { get; set; } } } |
運行效果
換言之,往後我們可以直接在ViewModel的屬性藉由DataType來抉擇對應要呈現捨麼樣子的html 。
那前面還有提到所謂可用於設定使用顯示/編輯模板呈現
我們改套用編輯模板
這裡我們修改多個屬性的ViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DataTypeViewModel { [DataType(DataType.EmailAddress)] public string Title { get; set; } [DataType(DataType.Currency)] public int Age { get; set; } } } |
Index.cshml部分我們只需要一句就能取代很多行input tag綁定,套用編輯模板。
預設都在HtmlHelper底下很多種和Model相應的模板可用
這裡用@Html.EditorForModel()
運行效果
EmailAddress
可將指定該特性的ViewModel屬性轉為type為email的input tag,可自動套用HTML5郵件格式的驗證。
這裡新增一個EmailAddressController和相應的Index檢視
Index.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @{ ViewData["Title"] = "EmailAddress"; } @model EmailAddressViewModel <form> <div> <label asp-for="Email"></label> <input asp-for="Email" /> <span asp-validation-for="Email"></span> </div> <div> <input type="submit" value="提交" /> </div> </form> |
EmailAddressViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class EmailAddressViewModel { [Display(Name = "郵件")] [EmailAddress()] public string Email { get; set; } } } |
運行效果
Display
前面一直用的主要就是用於做客製化label顯示
其包含order屬性,默認是採用升冪(序)由小到大排列,對於Display特性的Order屬性,可對ViewModel中屬性於編輯模板顯示順序進行排列(只限於編輯模板或顯示模板)。
新建一個Display控制器和相應Index檢視以及DisplayViewModel
Index檢視
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @{ ViewData["Title"] = "Display"; } @model DisplayViewModel <form> <div> @Html.EditorForModel() @*<label asp-for="Id"></label> <input type="text" asp-for="Id" /> <br /> <label asp-for="Name"></label> <input type="text" asp-for="Name" /> <br /> <label asp-for="Sex"></label> <input type="checkbox" asp-for="Sex" />*@ </div> </form> |
DisplayViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DisplayViewModel { [Display(Name="ID",Order =3)] public int Id { get; set; } [Display(Name="姓名",Order =1)] public string Name { get; set; } [Display(Name="性別",Order =2)] public bool Sex { get; set; } } } |
運行效果(預設bool會產生checkbox , ID為數字則呈現number選單)
默認情況下編輯模板會依照屬性由上至下依序排列。DisplayFormat
該屬性可用於對模型物件中屬性值進行格式化(Ex:貨幣、日期時間),藉由
DataFormatString ="格式類型"語法來指定要顯示的格式。
新建DisplayFormatController跟相應的Index檢視
還有對應ViewModel
DisplayFormatViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DisplayFormatViewModel { [Display(Name = "價格")] [DisplayFormat(DataFormatString = "{0:C}")] public double Price { get; set; } } } |
DisplayFormatController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using DotNet5App7.Models; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Controllers { public class DisplayFormatController : Controller { public IActionResult Index() { DisplayFormatViewModel model = new DisplayFormatViewModel() { Price = 45.58 }; return View(model); } } } |
這裡用[DisplayFormat(DataFormatString = "{0:C}")]去進行對應金錢格式設置,
該屬性可以去判定隸屬Server所在國家地理位置來做相應貨幣格式變換。
Index.cshtml
1 2 3 4 5 6 7 8 9 10 | @{ ViewData["Title"] = "DisplayFormat"; } @model DisplayFormatViewModel <div> <label asp-for="Price"></label> <input type="text" asp-for="Price" /> </div> |
當運行時會發現沒有套用轉為金錢格式的樣子
原因在於我們目前處於編輯文字輸入框的模式
要在對ViewModel中屬性做額外ApplyFormatInEditMode為true的設置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DisplayFormatViewModel { [Display(Name = "價格")] [DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)] public double Price { get; set; } } } |
再次運行即可
編輯模式在此也可用HtmlHelper提供方法搭配lambda語法來取代
1 2 3 4 5 6 7 8 9 10 11 | @{ ViewData["Title"] = "DisplayFormat"; } @model DisplayFormatViewModel <div> <label asp-for="Price"></label> <input type="text" asp-for="Price" /> @Html.EditorFor(m=>m.Price) </div> |
DisplayFormat中的ConvertEmptyStringToNull默認為true,可將模型的屬性值中若是空字串會被轉為null。
這裡擴充一個string屬性Name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DisplayFormatViewModel { [Display(Name = "價格")] [DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)] public double Price { get; set; } [DisplayFormat(ConvertEmptyStringToNull =false)] public string Name { get; set; } } } |
在檢視我們調整成一個表單提交的畫面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @{ ViewData["Title"] = "DisplayFormat"; } @model DisplayFormatViewModel <form method="post"> <div> <label asp-for="Price"></label> <input type="text" asp-for="Price" /> @Html.EditorFor(m => m.Price) </div> <div> <label asp-for="Name"></label> <input type="text" asp-for="Name" /> @Html.DisplayFor(m => m.Name) </div> <div> <input type="submit" value="提交" /> </div> </form> |
DisplayFormatController中調整從View傳進來模型接收的POST action method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using DotNet5App7.Models; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Controllers { public class DisplayFormatController : Controller { public IActionResult Index() { DisplayFormatViewModel model = new DisplayFormatViewModel() { Price = 45.58 }; return View(model); } [HttpPost] public IActionResult Index(DisplayFormatViewModel model) { return View(model); } } } |
運行效果
若這裡不去對屬性Name寫[DisplayFormat(ConvertEmptyStringToNull =false)]
或者寫[DisplayFormat(ConvertEmptyStringToNull =true)]
則Server-Side接收到會是null
在DisplayFormat中HtmlEncode屬性可協助我們是否要開啟或關閉要採用HTML來編碼
默認為true啟用的。
而NullDisplayText屬性則是當屬性值為null或空字串("")時,可設置預設為空要顯示的默認字串內容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace DotNet5App7.Models { public class DisplayFormatViewModel { [Display(Name = "價格")] [DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)] public double Price { get; set; } [DisplayFormat(NullDisplayText ="為空時的預設值")] public string Name { get; set; } } } |
留言
張貼留言