动态复选框-错误:收集是只读的

本文关键字:只读 复选框 错误 动态 | 更新日期: 2023-09-27 18:15:51

我对MVC4很陌生,我过去使用asp.net的经验一直与Webforms一起工作,所以我认为我需要一些小心的手握。提前感谢!

我正在创建一个简单的web应用程序,类似于选择彩票号码。此时,用户选择他们想要的任何数字(没有限制,从"1"开始)并将其发布到下一页,在那里我继续对用户选择的数字做一些事情。可供选择的数字数量是动态的,由复选框表示。

问题是,当提交视图时,我得到错误页面"Collection is read-only"。

Model - lotttonnumbers .csBool [] numbers存储用户检查过的数字。

namespace Lotto.Models
{
    public class LottoNumbers
    {
        public string name { get; set; }
        public bool[] numbers { get; set; }
        public LottoNumbers() {
            numbers = new bool[49];
        }
        public LottoNumbers(int limit)
        {
            numbers = new bool[limit];
        }
    }
}

在HomeController.cs…我声明了lotttonnumbers ln和

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Lotto.Models;
namespace Lotto.Controllers
{
    public class HomeController : Controller
    {
        public LottoNumbers ln;
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult SetNumbers()
        {
            ln = new LottoNumbers(30); 
            // 30 checkboxes will be generated on the view
            return View(ln);
        }
        [HttpPost]
        public ViewResult SetNumbers(LottoNumbers l)
        {
            // get checkbox values
            return View();
        }
    }
}

View - SetNumbers.cshtml

@model Lotto.Models.LottoNumbers
@{
    ViewBag.Title = "SetNumbers";
}
<h2>SetNumbers</h2>
@using (Html.BeginForm()) {
    <div>
        @Html.LabelFor(m => m.name)
        @Html.EditorFor(m => m.name)
    </div>
    <div id="numberlist">
    @for (int i = 0; i < Model.numbers.Length; i++)
    {
    <div class="item-number" style="">
        @Html.EditorFor(m => m.numbers[i])
        <label class="lbl-number" for="numbers[@i]">@(i+1)</label>
    </div>
    }
    </div>
    <div style="clear:both;">
        <input type="reset" value="Reset everything" />
        <input type="submit" value="Submit" />
    </div>
}

动态复选框-错误:收集是只读的

将数组更改为列表。

  public string Name { get; set; }
    public List<bool> Numbers { get; set; }
    public LottoNumbers()
    {
        Numbers = new List<bool>();
        for (var i = 0; i < 40; i++)
        {
            Numbers.Add(false);
        }
    }
    public LottoNumbers(int limit)
    {
        Numbers = new List<bool>();
        for (var i = 0; i < limit; i ++)
        {
            Numbers.Add(false);
        }
    }

那么你的视图将是

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(m => m.Name)
        @Html.EditorFor(m => m.Name)
    </div>
    <div id="numberlist">
        @for (var i = 0; i < Model.Numbers.Count; i++)
        {
            <div class="item-number" style="">
                @Html.CheckBox("Numbers[" + i.ToString() + "]")
                <label class="lbl-number" for="numbers[@(i + 1)]">@(i + 1)</label>
            </div>
        }
    </div>
    <div style="clear:both;">
        <input type="reset" value="Reset everything" />
        <input type="submit" value="Submit" />
    </div>
}

空引用异常

你很可能在提交后得到null引用异常,因为你没有将模型传递回视图。您将页面设置为期望lotttonnumbers模型。

[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
    // get checkbox values
    return View(); //Nothing being passed to the view
}

所以在post之后当你的代码到达这里

@foreach (var numberBool in Model.Numbers)

当模型为空时就会爆炸。你可以用几种方法来解决这个问题,这取决于你想要你的应用程序如何运行。如果你想让用户在提交后看到一个空白的数字列表,只需这样做,并在发回时添加一些成功消息

[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
    //process stuff
    ln = new LottoNumbers(30);
    return View(ln);
}

也可以简单地将用户重定向到索引页。无论哪种方式都会导致错误,因为您没有将带有数字的模型传递回视图。

如果您查看"Collection is read only"错误的堆栈跟踪,您可以看到它发生在模型绑定期间,这是当它试图从从表单post传递回来的数据中重新创建lotttonnumbers对象时。

你得到的错误是因为你初始化你的对象与数组的大小使用你的构造函数接受一个参数,但当它发回的数据,它不知道数组的大小需要当它重新创建对象。

要解决这个问题,最好使用List,并将大小作为lotttonnumbers对象的属性。

使用List意味着你不需要预先初始化数组的大小。将size作为属性意味着你可以将size嵌入到一个隐藏的输入变量中,这样它就可以被传递回控制器,并且它应该正确地进行模型绑定。