ASP.NET MVC 3 CheckboxFor 保留以前的值,尽管模型值
我正在尝试在 MVC 应用程序的登录页面上添加经典的“接受条款和条件”复选框。
如果用户接受条款和条件,但由于其他原因(密码错误等)而无法登录,那么我希望不要选中接受条款和条件复选框,因此用户被迫接受条款和条件每次登录尝试。
问题是,使用 Html.CheckboxFor(),在回发后,无论绑定的 Model 属性的值如何,复选框都会保留其先前的值。
这是代码,精简到最基本的内容。如果运行此代码,选中复选框,然后单击按钮,您将返回到复选框仍处于选中状态的表单,即使绑定的模型属性为 false。
模型:
namespace Namespace.Web.ViewModels.Account
{
public class LogOnInputViewModel
{
[IsTrue("You must agree to the Terms and Conditions.")]
public bool AcceptTermsAndConditions { get; set; }
}
}
验证属性:
public class IsTrueAttribute : ValidationAttribute
{
public IsTrueAttribute(string errorMessage) : base(errorMessage)
{
}
public override bool IsValid(object value)
{
if (value == null) return false;
if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
return (bool)value;
}
}
视图:
@model Namespace.Web.ViewModels.Account.LogOnInputViewModel
@using (Html.BeginForm()) {
@Html.CheckBoxFor(x => x.AcceptTermsAndConditions)
<input type="submit" value="Log On" />
}
控制器:
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
[HttpPost]
public ActionResult LogOn(LogOnInputViewModel input)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
我在asp上看到了建议 .net 向 CheckboxFor 添加 @checked
属性。我尝试了这个,制作了视图
@model Namespace.Web.ViewModels.Account.LogOnInputViewModel
@using (Html.BeginForm()) {
@Html.CheckBoxFor(x => x.AcceptTermsAndConditions, new { @checked = Model.AcceptTermsAndConditions })
<input type="submit" value="Log On" />
}
并且我看到了相同的行为。
感谢您的任何帮助/见解!
编辑:虽然我想覆盖回发的值,但如果 AcceptTermsAndConditions 验证失败,我希望保留消息(AcceptTermsAndConditions 上有一个验证属性要求它为 true),所以我不能使用 ModelState.Remove("AcceptTermsAndConditions") 这是 @counsellorben 给我的合理答案。我已经编辑了上面的代码以包含验证属性 - 向@counsellorben 道歉,因为最初没有更清楚。
I'm attempting to add a classic Accept Terms and Conditions checkbox on the log on page of an MVC application.
If the user accepts the Terms and Conditions, but fails to log on for some other reason (bad password etc), then I want the Accept T&Cs checkbox not to be checked, so the user is forced to accept the T&Cs on every log on attempt.
The problem is that using Html.CheckboxFor(), after a postback the checkbox retains its previous value, despite the value of the bound Model property.
Here's the code, stripped down to essentials. If you run this code up, check the checkbox, and click the button, you'll be returned to the form with the checkbox still checked, even though the bound model property is false.
The Model:
namespace Namespace.Web.ViewModels.Account
{
public class LogOnInputViewModel
{
[IsTrue("You must agree to the Terms and Conditions.")]
public bool AcceptTermsAndConditions { get; set; }
}
}
The validation attribute:
public class IsTrueAttribute : ValidationAttribute
{
public IsTrueAttribute(string errorMessage) : base(errorMessage)
{
}
public override bool IsValid(object value)
{
if (value == null) return false;
if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
return (bool)value;
}
}
The View:
@model Namespace.Web.ViewModels.Account.LogOnInputViewModel
@using (Html.BeginForm()) {
@Html.CheckBoxFor(x => x.AcceptTermsAndConditions)
<input type="submit" value="Log On" />
}
The Controller:
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
[HttpPost]
public ActionResult LogOn(LogOnInputViewModel input)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
I saw the suggestion on asp.net to add a @checked
attribute to the CheckboxFor. I tried this, making the view
@model Namespace.Web.ViewModels.Account.LogOnInputViewModel
@using (Html.BeginForm()) {
@Html.CheckBoxFor(x => x.AcceptTermsAndConditions, new { @checked = Model.AcceptTermsAndConditions })
<input type="submit" value="Log On" />
}
And I saw the same behaviour.
Thanks for any help/insights!
Edit: Although I want to override the posted back value, I wish to retain the message if validation of AcceptTermsAndConditions fails (there is a validation attribute on AcceptTermsAndConditions requiring it to be true), so I can't use ModelState.Remove("AcceptTermsAndConditions")
which was the otherwise sound answer @counsellorben gave me. I've edited the code above to include the validation attribute - apologies to @counsellorben for not being clearer originally.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要清除
AcceptTermsAndConditions
的 ModelState。根据设计,CheckBoxFor
和其他数据绑定帮助程序首先绑定到 ModelState,然后再绑定到模型(如果元素没有 ModelState)。将以下内容添加到您的 POST 操作中:You need to clear the ModelState for
AcceptTermsAndConditions
. By design,CheckBoxFor
and other data-bound helpers are bound first against the ModelState, and then against the model if there is no ModelState for the element. Add the following to your POST action: