[英]Can't Fix ASP.NET MVC Validation
我一直在尝试在表单上修复验证,但无法使其正常工作。 除非我输入有效的电子邮件地址,否则验证工作正常。 如果我这样做,则出于某种原因它只会跳过所有其他验证。
另外,如果我对控制器中所有内容的分割是否正确,请多多指教。 是否应该有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)
使用Modelstate.IsValid
。 它告诉您是否有任何模型错误已添加到ModelState。
public ActionResult Register(User user)
{
if (!ModelState.IsValid)
{
return View();
}
//your code
}
为了检查发布的模型是否有效,您需要在发布操作中检查ModelState.IsValid(请参见下面的示例)。
另外,如果我对控制器中所有内容的分割是否正确,请多多指教。 是否应该有2个动作(1个用于GET以便仅加载空表单,1个用于POST当用户提交表单时)? 我在那里做错了吗?
该方法是正确的,但您做不到的方法。
假设您具有Register.cshtml视图(而非局部视图):由于视图具有模型,因此应始终提供该模型。 因此,您的get方法应如下所示:
public ActionResult Register()
{
ViewBag.LoggedIn = false;
var model = new User();
return View(model);
}
对于post方法,有2种方法:
POST-REDIRECT-GET模式(PRG)-稍微复杂一点(但我认为这是更正确的方法)。 在发生错误和成功的情况下,Post方法而不是返回视图都应返回重定向结果。 为了处理无效的模型状态,您可以使用此处描述的一些方法
你的方式
[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"); }
首先,您的结构看起来是正确的,将操作拆分为具有区别的“获取”和“发布”操作是正确的,并且是实现此操作的一种好方法。
我无法测试,但我认为问题在于您未在控制器中正确处理验证; 您应该检查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/zh-cn/aspnet/core/tutorials/first-mvc-app/validation
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.