asp.net mvc 项目在使用 Ajax.BeginForm 时不显示带有自定义注释的错误消息

asp.net mvc project does not display error message with custom annotation when using Ajax.BeginForm

\ 请尝试建立一个项目,当用户填写时事通讯表格时, 如果电子邮件已经退出,表单应该特别验证输入。 问题在于,当我使用现有电子邮件插入数据时。 自定义注释不会为用户显示错误,它会运行 success ajax 方法,而不是向用户显示错误。 当我使用断点进行调试时,每件事代码都会运行预期的输出,尤其是出现自定义注释的错误消息。 我发现它适用于@Html.BeginForm(),但不适用于@Ajax.BeginForm()

// custom annotation code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using LiveShows.LiveClass;

namespace LiveShows
{
    public class CheckEmailAttribute : ValidationAttribute, IClientValidatable
    {
        public CheckEmailAttribute() :base("{0} Email Already Exit")
        {

        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
        {
            if(value != null)
            {
                var email = value.ToString();

                DetailInfo details = new DetailInfo();
                bool EmailExit = details.CheckEmailIfExist(email);
                if (EmailExit == true)
                {
                  // var ErrorMessage = FormatErrorMessage(validationContext.DisplayName);
                    return new ValidationResult("Email exist");
                }
                else
                {
                    return ValidationResult.Success;
                }
            }
            else
            {
                return new ValidationResult("Field Required");
            }

            //base.IsValid(value, validationContext);

    }
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage =
            FormatErrorMessage(metadata.GetDisplayName());

            rule.ValidationType = "checkemail";
            yield return rule;
        }


    }
}
// model code 
   public class EmailFeedsVm
    {
        public int id { get; set; }

        [Required (ErrorMessage ="Your Name is Required")]
        public string DisplayName { get; set; }

        [CheckEmail (ErrorMessage ="Email Already Exist")]
        [Required (ErrorMessage ="Email field is Required")]
        public string Email { get; set; }
        public string DateJoined { get; set; }
    }
// controller code with actiom

[HttpPost]
        public ActionResult NewsLetters(Vmclass.RegisterFeeds fd)
        {
            if (ModelState.IsValid) {
                var feeds = new LiveClass.RegistrationTasks();
                bool RegFeeds = feeds.RegisterEmailFeed(
                    fd.EmailFeeds.DisplayName, fd.EmailFeeds.Email);
                if (RegFeeds == true)
                {
                    return View(fd);
                }
                else
                {
                    return View(fd);
                }
            }
            return View(fd);

        } 
// javascript code 
var EmailMsg = '<h4>Thank You for Joining Us</h4> <p>We will Send You the most Exclusive Events</p>';

function hideLoader(){
    loadingUI.attr("style","none")
}

function Success()
{
    // hideLoader();
    Mymodal.modal('show');
    $("#msgHeading").text("Status");
    $("#status").html('<img src="../img/com/ok.png" />');
    $("#Content").html(EmailMsg);

}
function failure() {
    //    hideLoader();
    Mymodal.modal('show');
    msgHeading.text("Status");
    $("#status").html('<img src="../img/com/Cancel.png" />');
    $("#Content").text("Registration Failed");

}
// view code
   <p id="loading" style="display:none">Loading</p>
            @using (Ajax.BeginForm("NewsLetters", "Home", new AjaxOptions {

                HttpMethod="post",
                OnFailure = "failure",
                OnSuccess = "Success",

               LoadingElementId = "loader",


            }, new { id = "getEmail" }))
            {
                @Html.AntiForgeryToken()
                @Html.ValidationSummary()
                    <div class="form-group">
                        @Html.LabelFor(a => a.EmailFeeds.DisplayName, "Name", new { @class = "form-label" })
                        @Html.TextBoxFor(a => a.EmailFeeds.DisplayName, "Email",new {@class = "form-control" })
                        @Html.ValidationMessageFor(a => a.EmailFeeds.DisplayName)
                    </div>
                    <div class="form-group">
                      @Html.LabelFor(a => a.EmailFeeds.Email, new { @class = "form-label" })
                        @Html.TextBoxFor(a => a.EmailFeeds.Email, new { @class = "form-control" })
                        @Html.ValidationMessageFor(a=>a.EmailFeeds.Email)
                    </div>
                    <button class="btn btn-blue" id="sendEmail" type="submit" >  <img style="display:none" src="../img/ajax-img/smLoader.gif"  id="imgBtn" height="25" /> Done! </button>
            }
            </div>
           <div id="notify">
               <div class="notify">
                   <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModal-label">
                       <div class="modal-dialog" role="document">
                           <div class="modal-content">
                               <div class="modal-header">
                                   <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                                   <h4 class="modal-title" id="myModal-label"> <span id="msgHeading"></span> </h4>
                               </div>
                               <div class="modal-body">

                                   <div id="status">
                                   </div>
                                   <div id="Content">
                                   </div>

                               </div>
                               <div class="modal-footer">
                                   <div id="msgfooter"></div>
                                   <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

                               </div>
                           </div>
                       </div>
                   </div>
               </div>
       </div>

我在手表选项卡中也看到了这个错误

使用您当前的代码,即使 ModelState.IsValid return 为假,操作方法 return 也是一个查看结果。对于 ajax 调用,这是一个 200 OK 响应,因此转到成功处理程序。

如果视图是 ajax 表单提交,则 return 视图毫无意义。你可以做的是,如果它是一个 ajax 提交,return 一个包含所有模型验证错误的 JSON 响应,并在你的成功处理程序中检查这个 JSON 并显示适当的给用户的错误消息。

[HttpPost]
public ActionResult NewsLetters(Vmclass.RegisterFeeds fd)
{
   var list = new List<string>();
   if (!ModelState.IsValid)
   {
      var errors = ViewData.ModelState.Values
                         .SelectMany(f => f.Errors
                                          .Select(x => new {Error = x.ErrorMessage,
                                                  Exception =x.Exception})).ToList();
      return Json(new {Status="error",Errors = errors});

   }
  // to do : Your existing code to save
  return Json(new {Status="success"});
}

现在在您的成功句柄中检查

function Success(result) {
    if(result.Status==="error")
    {
      $.each(result.Errors, function(a, b) {
       alert(b.Error);
      });
    }
    else
    {
        $("#status").html("Succesfully saved")
    }
}

在这里我只是提醒每个错误。您可以更新该部分以在列表中显示错误并将其附加到 DOM.

如果您希望相同的操作方法用于 ajax 表单提交而不是 ajax 提交,您可以有条件地 return a json response/view结果。 Request.IsAjaxRequest() 方法在这里会派上用场

if(Request.IsAjaxRequest())
{
   return Json(new {Status="error",Errors = errors});
}
else
{
   return View(fd);
}