没有类型为“IEnumerable”的 ViewData 项具有键“PestType”

本文关键字:ViewData PestType SelectListItem 类型 IEnumerable | 更新日期: 2023-09-27 18:31:07

我正在学习MVC和实体框架,所以请接受我的问题...我正在尝试为我的模型类 SinglePest 的属性(枚举类型)创建一个下拉菜单这是模型:

public class SinglePest
{
    public int SinglePestId { get; set; }
    public PestType PestType { get; set; } // here is my problem
    public string Alias { get; set; }
    public string  TechName { get; set; }
    public string Markings { get; set; }
    public string SerialNumber { get; set; }
    public SourceType SourceType { get; set; }
    //virtual property
    public Source Source { get; set; }
}

这是害虫类型:

    public enum PestType
{
    Dog,
    Cat,
    Fox,
    Rabbit,
    Rat
}

这是控制器:

 [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create (//(SinglePest singlepest)
    [Bind(Include= "Alias, TechName, SerialNumber, PestType, Markings")] SinglePest singlepest)
    {
        try
        {
            if (ModelState.IsValid)
            {
                db.SinglePests.Add(singlepest);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
        }
        catch (DataException /* dex */)
        {
            ModelState.AddModelError("", "Unable to save changes, try again, if problem   persits contact your administrator");
        }
        //ViewBag.SerialNumber = new SelectList(db.Sources, "SerialNumber", "SerialNumber", singlepest.SerialNumber);
        return View(singlepest);
    }

这是我收到错误的视图(没有类型为"IEnumerable"的视图数据项具有键"PestType"):

<div class="editor-label">
        @Html.LabelFor(model => model.PestType, "Pest Type")
    </div>
    <div class="editor-field">
        @Html.DropDownList("PestType", String.Empty) // here is the error
        @Html.ValidationMessageFor(model => model.PestType.ToString())
    </div>

现在我看到了一些关于显示枚举的帖子,但我无法找到解决我的问题的方法。有人可以给我一些关于如何解决它的建议吗?

谢谢你的时间!

没有类型为“IEnumerable<SelectListItem>”的 ViewData 项具有键“PestType”

你有@Html.DropDownList("PestType", String.Empty),但第二个参数需要是一个IEnumerable<T>。 您将需要模型中的害虫列表,然后使用model.Pests例如,其中宠物是IEnumerable

编辑:基于评论...

但我想只展示各种类型的害虫(狗、猫等) 不是我数据库中的所有害虫

好的,这些是分类的,你能写一些类似的东西(手写所以检查语法)..

var pests = (from _context.Pests.Where(p => p.CategoryId == 1) select p.PestName).ToList();

如果您需要为枚举获取 IEnumerable(因为我不确定数据库是什么样子的),您可以使用...

Enum.GetValues(typeof(PestType))
            .OfType<PestType>()
            .Where(p => p == ??);

目前,您的模型仅包含一个存储值的位置,而不是用于填充下拉列表的数组/IEnumerable。

首先向模型添加一个 IEnumerable:

public class SinglePest
{
    public int SinglePestId { get; set; }
    public IEnumerable<PestType> Pests { get; set; }
    public PestType PestType { get; set; }
    public string Alias { get; set; }
    public string  TechName { get; set; }
    public string Markings { get; set; }
    public string SerialNumber { get; set; }
    public SourceType SourceType { get; set; }
    //virtual property
    public Source Source { get; set; }
}

在控制器中:

public ActionResult Create()
{    
    var model = new SinglePest();
    model.Pests = Enum.GetValues(typeof(PestType)).Cast<PestType>()
    return View(model);
}

以及您的观点:

@Html.DropDownListFor(m => m.PestType, Model.Pests);

抱歉,如果我从记忆中写了这个有任何错误......

我在 DropDownList 上找到了这篇文章对于枚举似乎它正在解决我的问题。

所以我刚刚用这段新代码改变了视图:

<div class="editor-label">
        @Html.LabelFor(model => model.PestType, "Pest Type")
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.PestType, new SelectList(Enum.GetValues(typeof( MvcTrackingSystem.Enums.PestType))))
        @Html.ValidationMessageFor(model => model.PestType)
    </div>

现在看起来它正在工作

关于DropDownListDropDownListFor之间的区别,我在这篇文章中找到了有用的信息

您可以在 GET Create 方法中非常简单地解决原始问题:

ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>());

这在你的 POST 创建方法中(验证失败并返回视图):

ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>(),
                                  singlepest.PestType);

如果要在视图中保持强类型,请使用:

@Html.DropDownListFor(model => model.PestType, ViewBag.PestType as SelectList)

如果您不介意弱类型版本,请使用更简单的版本:

@Html.DropDownList("PestType")

无论哪种情况,我都建议您在控制器中创建所有列表,而不是在视图中创建。

解释:

基本上,DropDownlist将在ViewData(即您的ViewBag设置)中搜索同名成员的选项列表(如果未明确提供列表)。

我模拟了整个项目(MVC5/VS2013),下面有更多代码供您参考。

控制器:

using PestTypeTest.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace PestTypeTest.Controllers
{
    public class PestTypeController : Controller
    {
        //
        // GET: /PestType/
        public ActionResult Index()
        {
            return RedirectToAction("Create");
        }
        public ActionResult Create()
        {
            ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>());
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(//(SinglePest singlepest)
        [Bind(Include = "Alias, TechName, SerialNumber, PestType, Markings")] SinglePest singlepest)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    //db.SinglePests.Add(singlepest);
                    //db.SaveChanges();
                    return RedirectToAction("Index");
                }
            }
            catch (DataException /* dex */)
            {
                ModelState.AddModelError("", "Unable to save changes, try again, if problem   persits contact your administrator");
            }
            //ViewBag.SerialNumber = new SelectList(db.Sources, "SerialNumber", "SerialNumber", singlepest.SerialNumber);
            ViewBag.PestType = new SelectList(Enum.GetValues(typeof(PestType)).OfType<PestType>(), singlepest.PestType);
            return View(singlepest);
        }
    }
}

Views''PestType''Create.cshtml

@model PestTypeTest.Models.SinglePest
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <h4>SinglePest</h4>
        <hr />
        @Html.ValidationSummary(true)
        <div class="form-group">
            @Html.LabelFor(model => model.PestType, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("PestType")
                @Html.ValidationMessageFor(model => model.PestType)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Alias, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Alias)
                @Html.ValidationMessageFor(model => model.Alias)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.TechName, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.TechName)
                @Html.ValidationMessageFor(model => model.TechName)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Markings, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Markings)
                @Html.ValidationMessageFor(model => model.Markings)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.SerialNumber, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.SerialNumber)
                @Html.ValidationMessageFor(model => model.SerialNumber)
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}