iT邦幫忙

0

custom Validation error message 沒有顯示在view

我實作了一個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>

2 個回答

0
YoChen
iT邦新手 2 級 ‧ 2019-09-04 10:32:01
最佳解答

首先,可能要請您提供繼承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
{
    // ...
}
看更多先前的回應...收起先前的回應...
wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 12:20:53 檢舉

還是不行=.= ,我在IsValid的條件判斷那邊if ((check_account_unique > 0)&&(value != null))有寫 Debug.WriteLine(check_account_unique+"ggg");顯示在output畫面,所以我很確定他有進入scope 也有正確的return出去,改不懂為什麼沒有正確的顯示在view 上,我用內建的require 有成功

YoChen iT邦新手 2 級 ‧ 2019-09-04 13:31:45 檢舉

方便讓我看一下您的View嗎

wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 13:38:39 檢舉

view 附在上面了,我更新了問題內容

YoChen iT邦新手 2 級 ‧ 2019-09-04 13:53:42 檢舉

看起來沒什麼問題,請問您是用一般的Form還是AjaxForm呢

wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 13:58:25 檢舉

@using (Ajax.BeginForm("Vendor_login", "MainPage", new AjaxOptions() { HttpMethod = "POST" }))
{

}
用Ajax.BeginForm

YoChen iT邦新手 2 級 ‧ 2019-09-04 14:10:32 檢舉

挖,這樣會有點麻煩~XDDD
因為AjaxForm沒辦法主動幫您更新頁面內容,所以您必須自己把ErrorMessage組回去才行

wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 14:13:00 檢舉

喔喔 所以問題點是在AjaxForm,那用一般的form 就可以顯示了?

YoChen iT邦新手 2 級 ‧ 2019-09-04 14:21:16 檢舉

是的,但一般Form最大的問題就是會跟Server要一個新的頁面(也就是畫面會閃一下),通常使用AjaxForm就是為了想避免這種情況

wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 14:24:04 檢舉

歐 感謝大大的提點,那組回去的寫法,可以跟我講一下觀念上應該怎麼做嗎?

YoChen iT邦新手 2 級 ‧ 2019-09-04 14:29:33 檢舉

由於資料驗證包含了前端後端驗證,使用AjaxForm的話,必須在前端驗證多下一些功夫,您可以參考Model Validation裡有個Remote的內建驗證屬性,可以在前端呼叫Server來驗證Client的輸入,算是個不同的解決方案~
詳情可以參考
https://docs.microsoft.com/zh-tw/aspnet/core/mvc/models/validation?view=aspnetcore-2.2#remote-attribute

YoChen iT邦新手 2 級 ‧ 2019-09-04 14:32:45 檢舉

至於一般Form的話,因為是丟給Server處理,Server會幫您把所有資訊組好再回傳頁面給您,所以您照您原本的方法寫就可以了

YoChen iT邦新手 2 級 ‧ 2019-09-04 14:42:33 檢舉

組回去的寫法,
您必須先從ModelState取得驗證錯誤的欄位錯誤訊息,然後將該資訊組成可以回傳的格式 e.g. JSON,然後在前端透過您在AjaxForm的AjaxOption裡註冊的JavaScript Function把資訊重新組回前端~

wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 14:47:35 檢舉

喔喔 我懂了 感謝大大堤點

0
小魚
iT邦大師 1 級 ‧ 2019-09-04 08:49:31

稍微看一下,
你只有在這裡有用到,

if ((ModelState.IsValid))

這會有問題,
通常在if後面的必須為布林值,
雖然我不知道為什麼可以編譯,
不過如果是轉成數字的話,
if後面的數字只要是大於0都會被當成true,
因為你的ModelState.IsValid是一個enum,
有可能永遠都是大於0,
比較正確的寫法應該是

if(ModelState.IsValid == ValidationResult.Success)
wolfsky95 iT邦新手 5 級 ‧ 2019-09-04 14:47:12 檢舉

感謝大大回復

我要發表回答

立即登入回答