无法修复 ASP.NET MVC 验证
Posted
技术标签:
【中文标题】无法修复 ASP.NET MVC 验证【英文标题】:Can't Fix ASP.NET MVC Validation 【发布时间】: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])@))" +
@"(?(\[)(\[(\d1,3\.)3\d1,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是否有效。
【参考方案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 方法,有两种方法:
POST-REDIRECT-GET 模式 (PRG) - 稍微复杂一点(但在我看来,这样做更正确)。 Post 方法而不是返回视图应该在错误和成功的情况下返回重定向结果。为了处理无效的模型状态,您可以使用here
中描述的一些方法你的方式
[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
希望这会有所帮助。
【讨论】:
以上是关于无法修复 ASP.NET MVC 验证的主要内容,如果未能解决你的问题,请参考以下文章
处理 OAuth 2.0 身份验证 - 在 ASP.NET MVC 应用程序中获取令牌重定向令牌响应
MVC Contrib 是不是兑现了提高 ASP.NET MVC 生产力的承诺
在 ASP.NET Core 2 中处理异常的推荐方法? [关闭]