我實作了一個class繼承ValidationAttribute,做一個客製化驗證,我碰到的問題是我很確定有進入觸發錯誤的scope ,有正確return ValidationResult,但是 error message 沒有顯示在view上,想請問各位大大堤點我一下
-----客製化驗證的class code------------------------------
public class Check_acccountAttribute : ValidationAttribute
{
private test_shoppingEntities db = new test_shoppingEntities();
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
int? check_account_unique = db.Database.SqlQuery<int>("Select Count(Account) from Customer Where Account=@AccountStr", new SqlParameter("AccountStr", value.ToString())).FirstOrDefault();
if ((check_account_unique > 0)&&(value != null))
{
Debug.WriteLine(check_account_unique+"ggg");
return new ValidationResult("會員帳號重複", new[] { "Account" });
}
else
{
return ValidationResult.Success;
}
}
}
--------------------------model code 只留下客製化驗證欄位code------------
[MetadataType(typeof(PartialCustomer))]
public partial class Customer
{
}
public class PartialCustomer
{
[Display(Name = "會員帳號")]
[Required(ErrorMessage = "Account必須輸入")]
[Check_acccount(ErrorMessage = "會員帳號重複")]
public string Account { get; set; }
}
-----------------controller action---------------------------
if ((ModelState.IsValid))
{
Debug.WriteLine("ModelState.IsValid1");
customer.CustomerId = "default";
db.Customer.Add(customer);
try
{
Debug.WriteLine("22222");
db.SaveChanges();
ModelState.Clear();
return JavaScript("alert('註冊會員成功!!!!');");
}
catch (Exception ex)
{
throw;
}
}
return View(customer);
**-------------view--------------------------------------------- **
@Html.EditorFor(model => model.Account, new { htmlAttributes = new { @class = "form-control", style = "width: 150px;height:50px;font-size:18px;" } })<br />
@Html.ValidationMessageFor(model => model.Account,"", htmlAttributes: new { @class = "", style = "font-size:18px; font-weight:bold;color: #FF4500;" })<br />
<label style="color:lightyellow;font-weight:bold;font-size:20px;">PassWord</label><br />
@Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control", style = "width: 150px;height:50px;font-size:18px;" } }) <br />
@Html.ValidationMessageFor(model => model.Password, "", htmlAttributes: new { @class = "", style = "font-size:18px; font-weight:bold;color: #FF4500;" })<br />
<input type="submit" value="註冊" class="btn btn-primary" style="margin-top:10px;width: 150px;height:50px;font-size:25px;" />
</div>
<div class="col-md-8 col-lg-8 col-sm-8">
@Html.ValidationSummary(true, "", htmlAttributes: new { @class = "", style = "font-size:18px; font-weight:bold;color: #FF4500;" })
</div>
首先,可能要請您提供繼承ValidationAttribute的完整Class,依照您的程式碼我猜應該是Check_acccountAttribute,不過還是確認一下,e.g.
public class Check_acccountAttribute : ValidationAttribute
{
// ...
}
再來Model的部分,既然您已經在ValidationAttribute填寫錯誤訊息了,ErrorMessage就不用再填寫一次了,可以改成這樣
public class PartialCustomer
{
[Display(Name = "會員帳號")]
[Required(ErrorMessage = "Account必須輸入")]
[Check_acccount]
public string Account { get; set; }
}
再來我們到View的地方,確認一下自己有沒有給Account ValidationMessage欄位,可能會像這樣
@Html.LabelFor(model => model.Account, htmlAttributes: new { @class = "control-label" })
@Html.EditorFor(model => model.Account, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Account, "", new { @class = "text-danger" }) // 這個一定要有,不然Error Message不知道要顯示在哪
最後我強迫症抓個小地方,Controller的地方
if (ModelState.IsValid) // 單層括號就好啦~XDDD
{
// ...
}
還是不行=.= ,我在IsValid的條件判斷那邊if ((check_account_unique > 0)&&(value != null))有寫 Debug.WriteLine(check_account_unique+"ggg");顯示在output畫面,所以我很確定他有進入scope 也有正確的return出去,改不懂為什麼沒有正確的顯示在view 上,我用內建的require 有成功
方便讓我看一下您的View嗎
view 附在上面了,我更新了問題內容
看起來沒什麼問題,請問您是用一般的Form還是AjaxForm呢
@using (Ajax.BeginForm("Vendor_login", "MainPage", new AjaxOptions() { HttpMethod = "POST" }))
{
}
用Ajax.BeginForm
挖,這樣會有點麻煩~XDDD
因為AjaxForm沒辦法主動幫您更新頁面內容,所以您必須自己把ErrorMessage組回去才行
喔喔 所以問題點是在AjaxForm,那用一般的form 就可以顯示了?
是的,但一般Form最大的問題就是會跟Server要一個新的頁面(也就是畫面會閃一下),通常使用AjaxForm就是為了想避免這種情況
歐 感謝大大的提點,那組回去的寫法,可以跟我講一下觀念上應該怎麼做嗎?
由於資料驗證包含了前端和後端驗證,使用AjaxForm的話,必須在前端驗證多下一些功夫,您可以參考Model Validation裡有個Remote的內建驗證屬性,可以在前端呼叫Server來驗證Client的輸入,算是個不同的解決方案~
詳情可以參考
https://docs.microsoft.com/zh-tw/aspnet/core/mvc/models/validation?view=aspnetcore-2.2#remote-attribute
稍微看一下,
你只有在這裡有用到,
if ((ModelState.IsValid))
這會有問題,
通常在if後面的必須為布林值,
雖然我不知道為什麼可以編譯,
不過如果是轉成數字的話,
if後面的數字只要是大於0都會被當成true,
因為你的ModelState.IsValid是一個enum,
有可能永遠都是大於0,
比較正確的寫法應該是
if(ModelState.IsValid == ValidationResult.Success)