[ASP NET MVC] 透過AJAX接收ModelState Errors顯示於對應欄位中

透過AJAX接收ModelState Errors顯示於對應欄位中

前言

 

在執行表單資料驗證時,前端大多透過ASP.NET MVC的Html.Helper產出data-val-*屬性(依據ViewModel Attribute設定),再搭配jQuery來進行Client端資料檢核;但若牽涉複雜商業邏輯檢核時就會交由後端驗證來處理,而驗證失敗的訊息會透過ModelState.AddModelError(key, errorMessage)方法來新增,最後在產生View畫面時會依照key找尋對應欄位來加註此errorMessage做顯示。如今在AJAX情況下,後端驗證所新增的ModelState Error方式沒變,但此時就必須要自行處理前端誤訊息的顯示工作,以下將進行實作的介紹。

 

 

實作方法

 

舉個簡單的例子,有一個使用者註冊介面,在輸入完畢後會以AJAX方式送出資料至後端,而在後端將驗證核該UserId是否已存在系統中,若存在的話就顯示錯誤訊息於UserId欄位下方,示意圖如下。

 

image

 

 

檢視一下View代碼,首先就是建立一個id為RegisterForm的表單,而前端驗證一如往常透過Http.Editor與Http.ValidationMessageFor兩個Html.Helper來產出相對應View Model屬性之Html元素。

 


@using (Html.BeginForm("SignUp", "User", FormMethod.Post, new { id = "RegisterForm" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <!-- input user id -->
    <div class="form-group">
        @Html.LabelFor(model => model.SingupUser.SysUserId)
        <div style="margin-bottom: 5px" class="col-md-9">
            @Html.EditorFor(model => model.SingupUser.SysUserId)
            @Html.ValidationMessageFor(model => model.SingupUser.SysUserId, "", new { @class = "text-danger" })
        </div>
    </div>

    <!-- input user email -->
    <div class="form-group">
        @Html.LabelFor(model => model.SingupUser.Email)
        <div style="margin-bottom: 5px" class="col-md-9">
            @Html.EditorFor(model => model.SingupUser.Email)
            @Html.ValidationMessageFor(model => model.SingupUser.Email, "", new { @class = "text-danger" })
        </div>
    </div>

    <!-- 略 -->
    <!-- 略 -->

    <!-- Sign up button -->
    <div class="form-group">
        <div class="col-md-offset-3 col-md-9">
            <input type="button" id="submitButton" value="Sign Up Ajax" class="btn btn-info" />
        </div>
    </div>

}

 

 

產出畫面及對應HTML碼如下 (HttpHelper產出UserId輸入方塊,名稱為SignupUser.SysUserId)

 

image

 

 

在Controller的SignUpAjax Action中檢查UserId是否存在,若是則透過ModelState.AddModelError()新增錯誤訊息;最後擷取所有Model Error資訊放置於Dcitionary容器中,連同其他資訊一併回應前端。

 

image

 

SignUpAjax Action代碼如下


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SignUpAjax(UserLoginViewModel viewModel)
{
    bool isSuccess = true;

    if (ModelState.IsValid)
    {
        // check if the same member id exists in system
        if (_serviceFactory.UserService.GetUserById(viewModel.SingupUser.SysUserId) != null)
        {
            ModelState.AddModelError("SingupUser.SysUserId", "The user id has already existed in system");
            isSuccess = false;
        }
        
        if (isSuccess)
        {
            // register user to db
            // ...
        }
       
    }

    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())
    };
    return Content(Newtonsoft.Json.JsonConvert.SerializeObject(returnData), "application/json");
}

 

 

最後只要在javacript中,將傳回的Model錯誤訊息顯示出來就大功告成了

 


// submit data to server
$('#submitButton').click(function () {

    var myForm = $("#RegisterForm");

    var validator = myForm.validate();
    if (myForm.valid()) {

        var dataForm = myForm.serialize();
        $.ajax({
            type: 'POST',
            url: '@Url.Action("SignUpAjax", "User")',
            data: dataForm,
            cache: false,
            async: false,
            success: function (data) {
                if (data.IsSuccess) {

                    alert('register done');
                    window.location = '@Url.Action("Login", "User")';

                } else {

                    if (data.ModelStateErrors != null) {
                        // show model state error
                        validator.showErrors(data.ModelStateErrors);
                        alert('please check all required info');
                    } else {
                        alert('register fail');
                    }
                }
            }
        });

    } 
});

 

 

測試輸入已存在UserId並點選Sign Up Ajax按鍵後,在後端新增之Model Error訊息正確顯示於對應位置上。

 

image


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !