当前位置 : 主页 > 网络编程 > ASP >

ASP.NET MVC 5表单验证和错误处理

来源:互联网 收集:自由互联 发布时间:2021-06-24
尝试在简单的联系表单上实现数据验证和错误处理.当我添加对ModelState.IsValid的检查时,我处于鸡蛋和鸡蛋状态.我已经看过其他类似的问题,我只是没有得到这个.从Web Forms迁移到MVC并挣扎
尝试在简单的联系表单上实现数据验证和错误处理.当我添加对ModelState.IsValid的检查时,我处于鸡蛋和鸡蛋状态.我已经看过其他类似的问题,我只是没有得到这个.从Web Forms迁移到MVC并挣扎.尝试根据正在发生的事情切换 HTML元素 – 成功/错误消息等.现在,甚至验证都不起作用.

现在我只是想让服务器端验证工作,但欢迎提供有关如何添加客户端验证的建议;例如,是否有必要使用jQuery或者有什么内容?

视图:

@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
    if (ViewData["Error"] == null && ViewData["Success"] == null)
    {
        <h3>Send us an email</h3>
        Html.ValidationSummary(true);
        <div class="form-group">
            <label class="sr-only" for="contact-email">Email</label>
            <input type="text" name="email" placeholder="Email..."   
                class="contact-email" id="contact-email">
        </div>
        <div class="form-group">
            <label class="sr-only" for="contact-subject">Subject</label>
            <input type="text" name="subject" placeholder="Subject..."
                class="contact-subject" id="contact-subject">
        </div>
        <div class="form-group">
             <label class="sr-only" for="contact-message">Message</label>
             <textarea name="message" placeholder="Message..." 
                 class="contact-message" id="contact-message"></textarea>
        </div>
        <button type="submit" class="btn">Send it</button>
        <button type="reset" class="btn">Reset</button>
    }   
    else if (ViewData["Error"] == null && ViewData["Success"] != null)
    {
        <h4>We will get back to you as soon as possible!</h4>
        <p>
            Thank you for getting in touch with us. If you do not hear 
            from us within 24 hours, that means we couldn't contact you 
           at the email provided. In that case, please feel free to call 
           us at (xxx) xxx-xxxx at any time.
        </p>
    }
    else if (ViewData["Error"] != null)
    {
        <h3>Oops!</h3>
        <p>
            We apologize. We seem to be having some problems.
        </p>
        <p>
            Please come back and try again later. Alternatively, 
            call us anytime at (xxx) xxx-xxxx.
        </p>
    } 
}

模型:

public class ContactModel
{
    [Required(ErrorMessage = "Email address is required")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Subject is required")]
    public string Subject { get; set; }

    [Required(ErrorMessage = "Message is required")]
    public string Message  { get; set; }
}

控制器:

[HttpPost]        
public ActionResult Contact(ContactModel contactModel)
{
    if (ModelState.IsValid)
    {
        try
        {
            MailMessage message = new MailMessage();

            using (var smtp = new SmtpClient("mail.mydomain.com"))
            {
                // Standard mail code here

                ViewData["Success"] = "Success";
             }
         }
         catch (Exception)
         {
             ViewData["Error"] 
                 = "Something went wrong - please try again later.";
                    return View("Error");
         }
     }
     return View();
}

错误视图:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Error</title>
</head>
<body>
    <hgroup>
        <h1>Error.</h1>
        <h2>An error occurred while processing your request.</h2>
    </hgroup>
</body>
</html>

更新 – 05/09/2017

根据Guruprasad的回答,如果ModelState.IsValid的计算结果为false,则表单上不会报告验证错误消息.

注意我必须更改AddModelError签名以不使用“Extension ex”参数:ModelState.AddModelError(“Error”,“Server side error occurred”);因为我不希望向用户报告系统错误.

另请注意,此时我只在服务器端尝试验证(尚未通过客户端验证).
我已经更新了Contact.cshtml视图,因为没有显示任何模型错误 – 我已经为验证错误包含了Bootstrap .has-error和.help-block CSS规则:

@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
    <h3>Send us an email</h3>
    Html.ValidationSummary(true);
    <div class="form-group has-error">
        <label class="sr-only" for="contact-email">Email</label>
        @Html.TextBoxFor(m => m.Email, new { type = "text", name = "email",
            placeholder = "Email..", @class = "contact-email" })
        @Html.ValidationMessageFor(model => model.Email, String.Empty, 
            new { @class="help-block" })
    </div>
    <div class="form-group has-error">
        <label class="sr-only" for="contact-subject">Subject</label>
        @Html.TextBoxFor(m => m.Subject, new { type = "text", 
            name = "subject", 
            placeholder = "Subject..", @class = "contact-subject" })
        @Html.ValidationMessageFor(model => model.Subject, String.Empty, 
            new { @class = "help-block" })
    </div>
    <div class="form-group has-error">
        <label class="sr-only" for="contact-message">Message</label>
        @Html.TextAreaFor(m => m.Message, new { name = "message", 
            placeholder = "Message..", @class = "contact-message" })
        @Html.ValidationMessageFor(model => model.Message, String.Empty, 
            new { @class = "help-block" })
    </div>
    <button type="submit" class="btn">Send it</button>
    <button type="reset" class="btn">Reset</button>

    if (ViewData["Success"] != null)
    {
        <h4>We will get back to you as soon as possible!</h4>
        <p>
            Thank you for getting in touch with us. If you do not hear 
            from us within 24 hours, that means we couldn't contact you 
            at the email provided. In that case, please feel free to 
            call us at (xxx) xxx-xxxx at any time.
        </p>
    }
}
您需要了解多种内容.让我一点一点地走吧.

>很高兴你知道你的模型已经设计好,但你的视图如何知道它有一个模型可以自己绑定,当发布表单内容时,服务器如何知道,有一个模型可以接收.所以在第一个实例中,您需要构建绑定模型的视图.要在视图中绑定模型,您需要首先获取引用/在顶部声明它,让视图知道,好的,这是一个模型,您可以生成我的视图.
>嗯,你有ValidationSummary为true,那么我建议,不要使用ViewData传递错误信息,你可以使用ModelState.AddModelError并让ValidationSummary处理它.作为旁注,您可能还需要处理this issue,并且您可以使用同一帖子中提到的答案解决相同问题.如果您不使用或不想使用Html.ValidationSummary,那么您可以坚持使用当前视图.
>现在,要显示成功消息,您可以使用TempData或ViewData,并遵循现在视图中的相同结构.这是one more post,让你继续努力.
> View部分的最后和最重要的是将模型属性绑定到View元素.使用Razor View扩展助手为您的模型生成View.你有@ Html.TextBoxFor,@ Html.TextAreaFor等,你也有@ Html.TextBox,@ Html.TextArea不是用于绑定模型属性,而是用于生成纯HTML视图.您可以在这些帮助程序中添加其他html属性,如下面的更新视图所示.我建议更多地了解这些助手可用的重载.

所以这是您的更新视图.

@model SOTestApplication.Models.ContactModel   @*getting model reference*@

@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
    <h3>Send us an email</h3>
    Html.ValidationSummary(true);
    <div class="form-group">
        <label class="sr-only" for="contact-email">Email</label>
        @Html.TextBoxFor(m => m.Email, new { type = "text", name = "email", placeholder = "Email..", @class = "contact-email" })
        @*Usage of helpers and html attributes*@
    </div>
    <div class="form-group">
        <label class="sr-only" for="contact-subject">Subject</label>
        @Html.TextBoxFor(m => m.Subject, new { type = "text", name = "subject", placeholder = "Subject..", @class = "contact-subject" })
    </div>
    <div class="form-group">
        <label class="sr-only" for="contact-message">Message</label>
        @Html.TextAreaFor(m => m.Message, new { name = "message", placeholder = "Message..", @class = "contact-message" })
    </div>
    <button type="submit" class="btn">Send it</button>
    <button type="reset" class="btn">Reset</button>
}
if (ViewData["Success"] != null)
{
    <h4>We will get back to you as soon as possible!</h4>
    <p>
        Thank you for getting in touch with us. If you do not hear
        from us within 24 hours, that means we couldn't contact you
        at the email provided. In that case, please feel free to call
        us at (xxx) xxx-xxxx at any time.
    </p>
}

控制器侧验证

这部分不多说,因为它看起来不错.但基于我上面提到的几点,我建议你添加ModelState.AddModelError而不是使用ViewData来获取错误消息.消除您在视图中的if条件,以便即使在回发后仍保留联系表单.现在,如果要在服务器端验证后保留值,则只需将模型传回到post方法中的视图.更新的控制器将是:

[HttpPost]
public ActionResult Contact(ContactModel contactModel)
{
     if (ModelState.IsValid)
     {
          try
          {
              MailMessage message = new MailMessage();
              using (var smtp = new SmtpClient("mail.mydomain.com"))
              {
                  // Standard mail code here
                  ViewData["Success"] = "Success";
              }
          }
          catch (Exception)
          {
              ModelState.AddModelError("Server side error occurred", ex.Message.ToString());
          }
     }
     return View(contactModel); //this will persist user entered data on validation failure
}

客户端验证

考虑到这一部分,您在应用程序中设置的内容很少.

>您需要添加Html.EnableClientValidation(true);和Html.EnableUnobtrusiveJavaScript(true);到您的申请.有各种可能的方法来添加它.您可以在appSettings下的Web.config文件中添加此内容以获取全局含义或者您可以在特定视图中添加此内容,如下面更新的View示例中所述.

Web中的全球含义.Config ex:

<appSettings>
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

>如果您注意到App_Start目录下的BundleConfig.cs文件,您会看到默认情况下创建的以下条目.这些是负责客户端验证的jquery东西.

jQuery和jQueryVal条目

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.unobtrusive*",
                    "~/Scripts/jquery.validate*"));

>下一步是添加对这些文件的引用/使用@section Scripts在_Layout.cshtml或任何特定视图中呈现这些包.当你在_Layout.cshtml中包含它时.无论您将此布局与其他视图一起使用,都会呈现这些脚本/包.所以基本上,你可以在哪里渲染它们.

例如,在添加对模型的引用后,我会在Contact.cshtml视图中立即呈现这些内容.

@section Scripts
{
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")
}

>最后要做的是,你需要使用@ Html.ValidationMessageFor razor扩展,让MVC对特定属性进行错误消息的绑定.此外,要在View中显示这些错误消息,您需要为模型中的每个属性指定ErrorMessage,因为您现在正在使用Required(ErrorMessage = …对于模型中的每个属性.还有更多要了解这些属性)如果你详细探讨它的东西.

添加了适当验证的更新视图.

@model SOTestApplication.Models.ContactModel
@section Scripts
{
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")
}
@using (Html.BeginForm("Contact", "Contacts", FormMethod.Post))
{

    <h3>Send us an email</h3>
    Html.ValidationSummary(true);
    Html.EnableClientValidation(true);
    Html.EnableUnobtrusiveJavaScript(true);
    <div class="form-group">
        <label class="sr-only" for="contact-email">Email</label>
        @Html.TextBoxFor(m => m.Email, new { type = "text", name = "email", placeholder = "Email..", @class = "contact-email" })
        @Html.ValidationMessageFor(m => m.Email)
    </div>
    <div class="form-group">
        <label class="sr-only" for="contact-subject">Subject</label>
        @Html.TextBoxFor(m => m.Subject, new { type = "text", name = "subject", placeholder = "Subject..", @class = "contact-subject" })
        @Html.ValidationMessageFor(m => m.Subject)
    </div>
    <div class="form-group">
        <label class="sr-only" for="contact-message">Message</label>
        @Html.TextAreaFor(m => m.Message, new { name = "message", placeholder = "Message..", @class = "contact-message" })
        @Html.ValidationMessageFor(m => m.Message)
    </div>
    <button type="submit" class="btn">Send it</button>
    <button type="reset" class="btn">Reset</button>
    if (ViewData["Success"] != null)
    {
        <h4>We will get back to you as soon as possible!</h4>
        <p>
            Thank you for getting in touch with us. If you do not hear
            from us within 24 hours, that means we couldn't contact you
            at the email provided. In that case, please feel free to call
            us at (xxx) xxx-xxxx at any time.
        </p>
    }
}

希望我已经用这些观点澄清了你的大部分疑虑.快乐的编码..

网友评论