有了功能卻沒有能阻擋錯誤的資料寫入資料庫中,這會是很嚴重的一件事情。但後端驗證該怎麼做到?
於是乎找到了「[ASP NET MVC] 透過AJAX接收ModelState Errors顯示於對應欄位中」Chirs前輩所寫的文章,將其方法應用在我們這次建立的專案之中。
那麼它是透過什麼方式來驗證?
透過Model驗證,加上jquery.validate來做前端的接收和顯示。
廢話不多說,就用實際做一遍就了解了。
上一篇文章中,我們寫好了整個Create的功能後,要加入驗證要做一些修改。
先從後端製作出要給前端的訊息來開始,首先我們先把Model延伸出MetaData來寫入Model驗證,也能在此設定Display Name等等的相關訊息,但這不是此篇的重點。
我們的Model叫做Customers所以我們就寫一個CustomersMetadata出來對照他,程式碼如下。
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace Ajax_CRUD_Model
{
[MetadataType(typeof(CustomersMetadata))]
public partial class Customers
{
public class CustomersMetadata
{
[Required]
[Display(Name = "客戶代號")]
public string CustomerID { get; set; }
[Required]
[Display(Name = "客戶名稱")]
public string CompanyName { get; set; }
[Display(Name = "聯絡窗口")]
public string ContactName { get; set; }
[Display(Name = "職務名稱")]
public string ContactTitle { get; set; }
[Display(Name = "地址")]
public string Address { get; set; }
[Display(Name = "所在城市")]
public string City { get; set; }
[Display(Name = "地區")]
public string Region { get; set; }
[Display(Name = "郵遞區號")]
public string PostalCode { get; set; }
[Display(Name = "國家")]
public string Country { get; set; }
[Display(Name = "連絡電話")]
public string Phone { get; set; }
[Display(Name = "傳真")]
public string Fax { get; set; }
}
}
}
寫完可以先執行一次確認是否有參照到此Metadata,從我們的DataTable去看Title的部分有沒有連動到就知道了。畫面如下。
在Metadata中有加入[Required]去驗證此欄位必填。我們後續會去驗證怎麼接收這個Model的部分。
Model驗證的部分都設定好後,接下來就是要寫Controller的部分。原先的程式碼如下。
[HttpPost]
public ActionResult Create(Customers customers)
{
if (customers != null && ModelState.IsValid)
{
this.custromService.Create(customers);
var returnData = new
{
// 成功與否
IsSuccess = true,
};
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}
else
{
var returnData = new
{
// 成功與否
IsSuccess = false,
};
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}
}
把它修改成下面。
[HttpPost]
public ActionResult Create(Customers customers)
{
var isSuccess = true;
var returnData = new
{
// 成功與否
IsSuccess = isSuccess,
// ModelState錯誤訊息
ModelStateErrors = ModelState.Where(x => x.Value.Errors.Count > 0)
.ToDictionary(k => k.Key, k => k.Value.Errors.Select(e => e.ErrorMessage).ToArray())
};
if (customers != null && ModelState.IsValid)
{
var message = this.custromService.Create(customers);
if (message != null)
{
isSuccess = false;
returnData = new
{
// 成功與否
IsSuccess = isSuccess,
// ModelState錯誤訊息
ModelStateErrors = ModelState.Where(x => x.Value.Errors.Count > 0)
.ToDictionary(k => k.Key, k => k.Value.Errors.Select(e => e.ErrorMessage).ToArray())
};
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}
else
{
isSuccess = false;
returnData = new
{
// 成功與否
IsSuccess = isSuccess,
// ModelState錯誤訊息
ModelStateErrors = ModelState.Where(x => x.Value.Errors.Count > 0)
.ToDictionary(k => k.Key, k => k.Value.Errors.Select(e => e.ErrorMessage).ToArray())
};
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}
}
ModelStateErrors是去抓取ModelState所蒐集的錯誤訊息,然後再加入returnData內回傳給前端。在「[ASP NET MVC] 透過AJAX接收ModelState Errors顯示於對應欄位中」Chirs前輩中都有介紹到,ModelState的錯誤訊息是如何抓取,有興趣的朋友可以在此篇找到答案。
如果有些時候在後端Model驗證不夠做使用,要自訂自己的回傳錯誤訊息,可以利用
ModelState.AddModelError("MyErrorMessage", "SystemErrorMessage");
然後透過與Controller同樣的方式去抓取到加入回傳的資料中,再回傳給前端即可。
最後還是要給前端去做顯示,所以我們要來修改前端的jQuery的部分。原程式碼如下。
<!--Ajax Create-->
<script>
function Create() {
var myForm = $("#CreateForm");
var dataForm = myForm.serialize();
var validator = myForm.validate();
$.ajax({
type: 'POST',
url: '@Url.Action("Create", "Customer")',
data: dataForm,
cache: false,
async: false,
dataType: 'json',
success: function (data) {
$('#Create').modal('hide');
alert('新增資料成功');
var page = window.location.hash
? window.location.hash.slice(1)
: 1;
fetchPage(page);
}
});
}
</script>
修改後如下。
<!--Ajax Create-->
<script>
function Create() {
var myForm = $("#CreateForm");
var dataForm = myForm.serialize();
var validator = myForm.validate();
$.ajax({
type: 'POST',
url: '@Url.Action("Create", "Customer")',
data: dataForm,
cache: false,
async: false,
dataType: 'json',
success: function (data) {
if (data.IsSuccess) {
$('#Create').modal('hide');
$('#CreateForm')[0].reset();
alert('新增資料成功');
var page = window.location.hash
? window.location.hash.slice(1)
: 1;
fetchPage(page);
}
else
{
if ($.isEmptyObject(data.ModelStateErrors == false)) {
//show model state error
validator.showErrors(data.ModelStateErrors);
}
else
{
alert('ErrorMessage');
}
}
}
});
}
</script>
validator會將對應的ModelStateErrors對應到相對的欄位中。
逐步執行就可以發現,Metadata所制定的Modle驗證中會產生一個對應的錯誤資料,如下;
而jQuery validator會產生一個對應的Label去對應該錯誤訊息,如下;
可以發現這些透過一個去對應到所有的資訊才能串起來。欄位的ID
也就是在表單輸入的 Model 的資料欄位 = Metadata 設定的對應資料 = Textbox id = validator 產生的 label id
這些地方都是互相關聯的,要特別注意到。
那麼要讓validator顯示有些自訂出來的ModelState.Error呢? 請參考下面的程式碼。
isSuccess = false;
ModelState.AddModelError("TestError", "TestErrorMessage");
returnData = new
{
// 成功與否
IsSuccess = isSuccess,
// ModelState錯誤訊息
ModelStateErrors = ModelState.Where(x => x.Value.Errors.Count > 0)
.ToDictionary(k => k.Key, k => k.Value.Errors.Select(e => e.ErrorMessage).ToArray())
};
return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
ModelState.AddModelError ->自訂的錯誤訊息,然而ModelStateErrors也會將這自訂的錯誤訊息加入回傳的內容中。
但我們沒有設定對應的位置給他去產生訊息,而我們希望他以警告視窗顯示該錯誤訊息,在jQuery該如何取得此自訂的錯誤訊息,就參考下面的代碼。
alert(data.ModelStateErrors.TestError);
最後面的TestError就是錯誤訊息的名稱,就可以取得該錯誤訊息的內容,顯示在警告視窗上面。
以上就是本篇想記錄的內容,如有更好方法或者有比較差的地方歡迎各位前輩指點出來,謝謝。