【问题标题】:Can't Fix ASP.NET MVC Validation无法修复 ASP.NET MVC 验证
【发布时间】:2017-12-10 02:33:28
【问题描述】:

一段时间以来,我一直在尝试修复表单上的验证,但无法使其正常工作。验证工作正常,除非我输入有效的电子邮件地址。如果我这样做了,那么它会出于某种原因跳过所有其他验证。

另外,如果我在拆分控制器中的所有内容时做得正确,我将不胜感激。是否应该有 2 个操作(1 个用于 GET 仅加载空表单,1 个用于 POST 用户提交时)?我在那里做错了吗?

编辑: 更正:如果我输入有效的电子邮件地址,则表单提交正常并忽略其他验证。如果我没有有效的电子邮件地址,验证会检查所有内容。

这是我的模型类:

public class User
{
    public int ID { get; set; }

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

    [DisplayName("Email")]
    [DataType(DataType.EmailAddress)]
    [Required(ErrorMessage = "Email is required")]
    [RegularExpression(
        @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
            @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
        ErrorMessage = "Invalid email")]
    public string Email { get; set; }

    [DisplayName("Password")]
    [DataType(DataType.Password)]
    [Required(ErrorMessage = "Password required")]
    [MinLength(6, ErrorMessage = "Min 6 characters")]
    public string Password { get; set; }
}

这是我的控制器:

    public ActionResult Register()
    {
        ViewBag.LoggedIn = false;

        return View();
    }

    [HttpPost]
    public ActionResult Register(User user)
    {
        ViewBag.LoggedIn = false;

        user.Password = PasswordHash.CreateHash(user.Password);

        using (var context = new FoundationContext())
        {
            // if user exists
            if (context.Users.FirstOrDefault(n => n.Email == user.Email) != null) return Login(true);

            context.Users.Add(user);
            context.SaveChanges();
        }

        return View("~/Views/Home.Index.cshtml");
    }

这是我的表格:

    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                <div class="col-md-10 text-center">
                    <input type="submit" value="Register" class="btn btn-primary" />
                </div>
            </div>
        </div>
    }

当然还有身体的底部包括:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)

【问题讨论】:

  • 在HttpPost动作ModelState.IsValid中不检查Model是否有效。

标签: c# asp.net-mvc unobtrusive-validation


【解决方案1】:

为了检查发布的模型是否有效,您需要在发布操作中检查 ModelState.IsValid(参见下面的示例)。

另外,如果我在拆分控制器中的所有内容时做得正确,我将不胜感激。是否应该有 2 个操作(1 个用于 GET 仅加载空表单,1 个用于 POST 用户提交时)?我在那里做错了吗?

方法是对的,但你做的方式不对。

假设您有一个 Register.cshtml 视图(不是部分视图): 由于视图具有模型,因此您应该始终提供它。所以你的 get 方法应该是这样的:

public ActionResult Register()
{
    ViewBag.LoggedIn = false;
    var model =  new User();
    return View(model);
}

对于 post 方法,有两种方法:

  1. POST-REDIRECT-GET 模式 (PRG) - 稍微复杂一点(但在我看来,这样做更正确)。 Post 方法而不是返回视图应该在错误和成功的情况下返回重定向结果。为了处理无效的模型状态,您可以使用here

  2. 中描述的一些方法
  3. 你的方式

    [HttpPost]
    public ActionResult Register(User user)
    {
      ViewBag.LoggedIn = false;
      if(!this.ModelState.IsValid)
      {
         return View(user);
         //this will render a view with preserved invalid model state so all the values with the corresponding error messages will be shown.
      }
    
      user.Password = PasswordHash.CreateHash(user.Password);
    
      using (var context = new FoundationContext())
      {
          // if user exists
          if (context.Users.FirstOrDefault(n => n.Email == user.Email) != null) return Login(true);
    
          context.Users.Add(user);
          context.SaveChanges();
      }
    
      return RedirectToAction("Index", "Home");
    }
    

【讨论】:

    【解决方案2】:

    使用Modelstate.IsValid。它会告诉您是否已将任何模型错误添加到 ModelState。

    public ActionResult Register(User user)
    {
        if (!ModelState.IsValid) 
        {
           return View();
        }
    
        //your code
    }
    

    【讨论】:

      【解决方案3】:

      首先,您的结构似乎是正确的,将操作拆分为有区别的 Get 和 Post 操作是正确的,并且是一种很好的方法。

      我无法测试,但我认为问题在于您没有在控制器中正确处理验证;您应该检查 ModelState 是否有效。

          [HttpPost]
          public ActionResult Register(User user)
          {
              if (ModelState.IsValid)
              {
                  ViewBag.LoggedIn = false;
      
                  user.Password = PasswordHash.CreateHash(user.Password);
      
                  using (var context = new FoundationContext())
                  {
                      // if user exists
                      if (context.Users.FirstOrDefault(n => n.Email == user.Email) != null) return Login(true);
      
                      context.Users.Add(user);
                      context.SaveChanges();
                  }
      
                  return View("~/Views/Home.Index.cshtml");
              }
              return View(user);
          }
      

      如果模型中存在错误(基于您使用 DataAnnotations 放置的规则),则采用这种方式。

      我也不确定您的 DataAnnotations 属性是否正确: 有些与本文中使用的不同:

      https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/validation

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-12
        • 1970-01-01
        相关资源
        最近更新 更多