具有键“CategoryId”的 ViewData 项的类型为“System.Int32”,但必须是“IEnumerable<SelectListItem>”类型?

29

我的代码之前是可以运行的。我不知道是什么原因导致它现在不能运行,而且我似乎也无法解决它。我看到有人建议重置ModelState(ModelState.Clear();),但这并没有帮助我。此外,由于我对MVC还比较新,所以情况更加棘手。感谢任何帮助。

控制器:

    public ActionResult Create()
    {
        ActiveDirectoryModel adm = new ActiveDirectoryModel();
        ViewBag.notifyto = adm.FetchContacts();
        var model = Populate();


        return View(model);
    } 

    [HttpPost]
    public ActionResult Create(CreateViewModel model)
    {
        if (ModelState.IsValid)
        {
            model.leaf.Date = DateTime.Now.Date;
            model.leaf.Category = model.CategoryId;
            model.leaf.SubCategory = model.SubCategoryId;
            model.leaf.AssignedTo = model.AssignedToId;
            model.leaf.CoAssignedTo = model.CoAssignedToId;
            model.leaf.Status = model.StatusId;
            model.leaf.Priority = model.PriorityId;
            //model.lead.Parent = model.ParentID;

            db.LeafItems.AddObject(model.leaf);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(model);
    }

    public CreateViewModel Populate()
    {
        ActiveDirectoryModel adm = new ActiveDirectoryModel();
        var model = new CreateViewModel
        {
            AssignedToItems = adm.FetchContacts(),
            CoAssignedToItems = adm.FetchContacts(),
            NotifyToItems = adm.FetchContacts(),
            CategoryItems =
                from c in new IntraEntities().CategoryItems.ToList()
                select new SelectListItem
                {
                    Text = c.Name,
                    Value = c.ID.ToString()
                },
            SubCategoryItems =
                from sc in new IntraEntities().SubCategoryItems.ToList()
                select new SelectListItem
                {
                    Text = sc.Name,
                    Value = sc.ID.ToString()
                },
            StatusItems =
                from s in new IntraEntities().StatusItems.ToList()
                where s.IsPriority == false
                select new SelectListItem
                {
                    Text = s.Name,
                    Value = s.ID.ToString()
                },
            PriorityItems =
                from p in new IntraEntities().StatusItems.ToList()
                where p.IsPriority == true
                select new SelectListItem
                {
                    Text = p.Name,
                    Value = p.ID.ToString()
                }
        };
        return model;
    }

视图:

<div class="createTopInner">
    <div class="editor-label">
        @Html.LabelFor(model => model.leaf.Category)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.CategoryId, Model.CategoryItems, "")
        @Html.ValidationMessageFor(model => model.leaf.Category)
    </div>
</div>

模型:

    public int CategoryId { get; set; }
    public IEnumerable<SelectListItem> CategoryItems { get; set; }

1
我通过运行populate方法来解决了这个问题,如果ModelState.IsValid = false。 一旦8小时过去,我就可以将其作为真正的答案发布。在那之前,我不想让任何人浪费时间。 - Ber53rker
2个回答

51

如果在 POST 操作中,您的 ModelState 无效,则需要重新填充 SelectList 属性:

if( ModelState.IsValid ) 
{
    // save and redirect
    // ...
}

// repopulate your SelectList properties:
model.CategoryItems = GetCategories();

return View(model);

不要重新填充整个模型,否则您可能会丢失用户进行的任何更改。


谢谢。它仍然保留了值。但是你的解决方案显然更安全。 - Ber53rker
@Dismissile,你能提供更多相关信息吗?我们为什么需要重新填充选择列表,这样做有什么副作用吗?谢谢。 - Avneesh Srivastava
1
@AvneeshSrivastava MVC是无状态的。当您进行POST操作时,它将重新呈现整个视图,并且在POST中未发送的所有数据都将丢失。当您提交表单时,只会提交所选值,而不是整个项目列表。您需要重新填充它,以便再次拥有完整的列表。 - Dismissile

0

我找到的另一种解决方案是使用隐藏字段。因此,在您的情况下,您可以按照以下步骤操作:

@Html.HiddenFor(model => model.CategoryId)

现在还有另一个字段表格也会被提交,并在相应的模型中设置CategoryId。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接