Asp.net mvc 3 将mvc3单选按钮绑定到模型的正确方法

Asp.net mvc 3 将mvc3单选按钮绑定到模型的正确方法,asp.net-mvc-3,Asp.net Mvc 3,我有一个视图,其中包含我的网站条款和条件的单选按钮列表 e、 g 是 @Html.radioButton(model=>model.TermsAndConditions,“True”) 不 @Html.radioButton(model=>model.TermsAndConditions,“False”, 新建{Checked=“Checked”}) @Html.ValidationStyledMessageFor(model=>model.TermsAndConditions) 如果用户在没

我有一个视图,其中包含我的网站条款和条件的单选按钮列表

e、 g

是
@Html.radioButton(model=>model.TermsAndConditions,“True”)
不
@Html.radioButton(model=>model.TermsAndConditions,“False”,
新建{Checked=“Checked”})
@Html.ValidationStyledMessageFor(model=>model.TermsAndConditions)
如果用户在没有任何错误的情况下完成表单,则一切正常。但是,如果我执行服务器端验证并且页面刷新,则会丢失用户为radiobutton所做的选择,并且所选的radiobutton会返回默认的false字段

我是如何绑定radiobutton的?如果用户选择true,即使在服务器端验证之后也会保持该值


任何建议都很好

我遇到了一个类似的问题,通过在控制器中设置ViewData值来跟踪用户选择的内容,从而解决了这个问题。

我真的不知道,因为您还没有显示代码,但我怀疑如果服务器端验证失败,您只是返回了原始视图。失败时,您需要使用提交的模型填充视图,就像返回任何其他验证错误一样。否则,您将获得默认模型值(对于注册布尔值,该值始终为false)


也许您可以发布您的服务器端代码?

为了确保在服务器端验证后保留用户的选择,您需要在此处执行一些操作

a) 将每个收音机的“选中”属性绑定到视图中的模型,例如:

Yes
@Html.RadioButtonFor(model => model.TermsAndConditions, "True", model.TermsAndConditions == true ? new { Checked = "checked" } : null)
No
@Html.RadioButtonFor(model => model.TermsAndConditions, "False", model.TermsAndConditions == false ? new { Checked = "checked" } : null)
public ActionResult SomeForm()
{
    return View(new SomeModel { TermsAndConditions = false });
}
[HttpPost]
public ActionResult SomeForm(SomeModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    // Do other stuff here
}
b) 要在首次显示视图时定义初始默认值,请在GET请求(在控制器操作中)中初始化返回到视图的模型,例如:

Yes
@Html.RadioButtonFor(model => model.TermsAndConditions, "True", model.TermsAndConditions == true ? new { Checked = "checked" } : null)
No
@Html.RadioButtonFor(model => model.TermsAndConditions, "False", model.TermsAndConditions == false ? new { Checked = "checked" } : null)
public ActionResult SomeForm()
{
    return View(new SomeModel { TermsAndConditions = false });
}
[HttpPost]
public ActionResult SomeForm(SomeModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    // Do other stuff here
}
b) 在[HttpPost]控制器操作中,确保在验证失败时返回模型,例如:

Yes
@Html.RadioButtonFor(model => model.TermsAndConditions, "True", model.TermsAndConditions == true ? new { Checked = "checked" } : null)
No
@Html.RadioButtonFor(model => model.TermsAndConditions, "False", model.TermsAndConditions == false ? new { Checked = "checked" } : null)
public ActionResult SomeForm()
{
    return View(new SomeModel { TermsAndConditions = false });
}
[HttpPost]
public ActionResult SomeForm(SomeModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    // Do other stuff here
}

这样,当验证失败后在响应中呈现视图时,它将具有传入的实际模型状态(从而保持用户的选择)。

对于简短的回答,您需要做三件事:

  • 从第二个单选按钮中删除
    新建{Checked=“Checked”}
    。此硬编码的选中值将覆盖所有魔法
  • 从控制器操作返回ViewResult时,为其提供一个模型类的实例,其中TermsAndConditions为false。这将提供所需的默认false值,以便为您预选false单选按钮
  • 使用
    true
    false
    作为单选按钮的值,而不是
    “true”
    “false”
    。这是因为您的属性类型为
    bool
    。严格地说,您碰巧为
    true
    false
    选择了正确的字符串表示形式,但RadioButtonFor方法的值参数的类型为
    object
    。最好传入要比较的实际类型,而不是自己将其转换为字符串。下面将对此进行详细介绍
  • 下面是深入讨论的内容:

    框架希望自动为您完成所有这一切,但您在前两件事情上做得不正确,这使得您必须与框架抗争以获得所需的行为

    RadioButtonOn方法对指定属性的值调用
    .ToString()
    ,并将其与创建单选按钮时传入的值的
    .ToString()
    进行比较。如果它们相等,则它会在内部设置
    isChecked=true
    ,并最终在HTML中呈现
    checked=“checked”
    。这就是它决定检查哪个单选按钮的方式。它只是将单选按钮的值与属性的值进行比较,并检查匹配的值

    您可以用这种方式渲染几乎任何属性的单选按钮,它将神奇地工作。字符串、整数甚至枚举类型都可以工作!任何具有返回唯一表示对象值的字符串的
    ToString
    方法的对象都将工作。您只需确保将单选按钮的值设置为您的属性实际可能具有的值。最简单的方法就是传入值本身,而不是值的字符串表示形式。让框架为您将其转换为字符串

    (由于您碰巧传入了正确的字符串表示形式
    true
    false
    ,因此只要您修复了两个实际错误,这些值就可以工作,但传入实际值而不是它们的字符串仍然是明智的。)

    您的第一个真正错误是对“否”单选按钮硬编码
    Checked=“Checked”
    。这将覆盖框架试图为您执行的操作,并导致始终选中此单选按钮

    显然,您希望预选“否”单选按钮,但您必须以与上述所有内容兼容的方式进行操作。您需要为视图提供一个模型类的实例,其中TermsAndConditions设置为false,并让它将其“绑定”到单选按钮。通常,响应URL的初始GET请求的控制器操作根本不会为视图提供模型类的实例。通常,您只需
    返回视图()。但是,由于希望选择默认值,因此必须为视图提供TermsAndConditions设置为false的模型实例

    下面是一些说明所有这些的源代码:

    您可能已经拥有的某种帐户类。(视图的模型):

    控制器中的某些方法:

    //This handles the initial GET request.
    public ActionResult CreateAccount()
    {
        //this default instance will be used to pre-populate the form, making the "No" radio button checked.
        var account = new Account
        {
            TermsAndConditions = false
        };
    
        return View( account );
    }
    
    //This handles the POST request.
    [HttpPost]
    public ActionResult CreateAccount( Account account )
    {
        if ( account.TermsAndConditions )
        {
            //TODO: Other validation, and create the account.
            return RedirectToAction( "Welcome" );
        }
        else
        {
            ModelState.AddModelError( "TermsAndConditionsAgreement", "You must agree to the Terms and Conditions." );
            return View( account );
        }           
    }
    
    //Something to redirect to.
    public ActionResult Welcome()
    {
        return View();
    }
    
    整个视图:

    @model Account
    @{
        ViewBag.Title = "Create Account";
    }
    @using ( Html.BeginForm() )
    {
        <div>
            <span>Do you agree to the Terms and Conditions?</span>
            <br />
            @Html.RadioButtonFor( model => model.TermsAndConditions, true, new { id = "TermsAndConditions_true" } )
            <label for="TermsAndConditions_true">Yes</label>
            <br />
            @Html.RadioButtonFor( model => model.TermsAndConditions, false, new { id = "TermsAndConditions_false" } )
            <label for="TermsAndConditions_false">No</label>
            <br />
            @Html.ValidationMessage( "TermsAndConditionsAgreement" )
        </div>
        <div>
            <input id="CreateAccount" type="submit" name="submit" value="Create Account" />
        </div>
    }
    
    @模型帐户
    @{
    ViewBag.Title=“创建帐户”;
    }
    @使用(Html.BeginForm())
    {
    你同意这些条款和条件吗?
    
    @Html.RadioButton(model=>model.TermsAndConditions,