C# 动态复选框-错误:集合为只读

C# 动态复选框-错误:集合为只读,c#,asp.net,asp.net-mvc-4,visual-studio-2012,C#,Asp.net,Asp.net Mvc 4,Visual Studio 2012,我对MVC4很陌生,我过去使用asp.net的经验一直在使用Webforms,所以我想我需要一些小心的手。提前谢谢你 我正在创建一个简单的web应用程序,类似于选择乐透号码。此时,用户选择他们想要的数字(没有限制,以“1”开头),并将其发布到下一页,在那里我继续对用户选择的数字进行操作。可供选择的数字数量是动态的,并由复选框表示 问题是,提交视图时,我会看到错误页面“Collection is read-only” 模型-LottoNumbers.cs bool[]number用于存储用户已检查

我对MVC4很陌生,我过去使用asp.net的经验一直在使用Webforms,所以我想我需要一些小心的手。提前谢谢你

我正在创建一个简单的web应用程序,类似于选择乐透号码。此时,用户选择他们想要的数字(没有限制,以“1”开头),并将其发布到下一页,在那里我继续对用户选择的数字进行操作。可供选择的数字数量是动态的,并由复选框表示

问题是,提交视图时,我会看到错误页面“Collection is read-only”

模型-LottoNumbers.cs bool[]number用于存储用户已检查的数字

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中。。。 我宣布了LottonMembers 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();
        }
    }
}
查看-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>

}
@model Lotto.Models.LottoNumbers
@{
ViewBag.Title=“SetNumbers”;
}
设定值
@使用(Html.BeginForm()){
@LabelFor(m=>m.name)
@EditorFor(m=>m.name)
@对于(int i=0;im.numbers[i])
@(i+1)
}
}

如果查看“Collection is read only”(集合为只读)错误的堆栈跟踪,可以看到它是在模型绑定期间发生的,即它试图从表单post传回的数据重新创建LottonMembers对象时发生的

之所以会出现错误,是因为您使用接受参数的构造函数使用数组大小初始化对象,但当它发回数据时,它不知道重新创建对象时数组需要的大小

要解决这个问题,最好使用列表,并将大小作为LottoNumbers对象的属性


使用列表意味着您不必预先初始化数组的大小。将大小作为属性意味着您可以将大小嵌入到隐藏的输入变量中,以便将其传递回控制器,并且它应该正确地进行模型绑定。

将数组更改为列表

  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);
        }
    }
所以当你的代码到达这里后

@foreach (var numberBool in Model.Numbers)
当模型为空时,它会爆炸。您可以通过多种方式修复此问题,具体取决于您希望应用程序的运行方式。如果您希望用户在提交后看到一个空白的数字列表,只需执行此操作,并在回邮时添加一些成功消息

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

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

非常感谢您的解释!那我就用清单。如果我有足够的代表,我会投赞成票;我回答得太慢了,但我会投你一票@保宾德:我也会投你一票,因为我正要加上一个例子,但你比我强。。。团队合作!你为我节省了很多时间,因为我需要复习一下如何使用列表。非常感谢。奇怪的是,在提交页面后,@foreach行上出现了一个NullReferenceException。我不明白…添加了一个“空引用异常”部分来解释为什么会出现空引用异常,这也难怪。我已经超越了自己。谢谢你的耐心!现在是另一个问题。。。我找回了在视图中输入的变量名,但是列表显示了所有的假值,即使我选中了一些框。修复了我的问题-我将视图中的foreach更改为for循环,并使用@Html.EditorFor(m=>m.Numbers[index])
@foreach (var numberBool in Model.Numbers)
[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
    //process stuff
    ln = new LottoNumbers(30);
    return View(ln);
}