C# 具有键';XXX和x27;类型为';System.Int32';但必须为'型;IEnumerable<;选择列表项>';
我有以下视图模型C# 具有键';XXX和x27;类型为';System.Int32';但必须为'型;IEnumerable<;选择列表项>';,c#,asp.net-mvc,C#,Asp.net Mvc,我有以下视图模型 public class ProjectVM { .... [Display(Name = "Category")] [Required(ErrorMessage = "Please select a category")] public int CategoryID { get; set; } public IEnumerable<SelectListItem> CategoryList { get; set; }
public class ProjectVM
{
....
[Display(Name = "Category")]
[Required(ErrorMessage = "Please select a category")]
public int CategoryID { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
....
}
在我看来
@model ProjectVM
....
@using (Html.BeginForm())
{
....
@Html.LabelFor(m => m.CategoryID)
@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-")
@Html.ValidationMessageFor(m => m.CategoryID)
....
<input type="submit" value="Create" />
}
@model ProjectVM
....
@使用(Html.BeginForm())
{
....
@LabelFor(m=>m.CategoryID)
@Html.DropDownListFor(m=>m.CategoryID,Model.CategoryList,“-请选择-”)
@Html.ValidationMessageFor(m=>m.CategoryID)
....
}
视图显示正确,但在提交表单时,我收到以下错误消息
InvalidOperationException:具有键“CategoryID”的ViewData项的类型为“System.Int32”,但必须为“IEnumerable”类型
使用
@Html.DropDownList()
方法时也会出现相同的错误,如果我使用ViewBag
或ViewData
传递SelectList,则错误意味着CategoryList
的值为空(结果是DropDownListFor()
方法要求第一个参数的类型为IEnumerable
)
您没有为CategoryList
中每个SelectListItem
的每个属性生成输入(您也不应该这样做),因此SelectList
的值不会发布到控制器方法,因此POST方法中的model.CategoryList
的值为null
。如果返回视图,必须首先重新指定CategoryList
的值,就像在GET方法中所做的那样
public ActionResult Create(ProjectVM model)
{
if (!ModelState.IsValid)
{
model.CategoryList = new SelectList(db.Categories, "ID", "Name"); // add this
return View(model);
}
// Save and redirect
}
解释内部工作原理(源代码可以是)
DropDownList()
和DropDownListFor()
的每个重载最终调用以下方法
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
这反过来又叫
private static IEnumerable<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
由于属性CategoryID
的类型为int
,因此无法将其强制转换为IEnumerable
,并引发异常(在MvcResources.resx
文件中定义为)
具有键“{0}”的ViewData项属于类型“{1}”,但必须属于类型“{2}”。
我也遇到了同样的问题,当我试图发布表单时,得到了一个无效的ModelState。对我来说,这是由于将CategoryId设置为int导致的,当我将其更改为string时,ModelState是有效的,Create方法按预期工作。根据stephens(user3559349)的说法,这可能很有用:
@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList ?? new List<SelectListItem>(), "-Please select-")
@Html.DropDownListFor(m=>m.CategoryID,Model.CategoryList??新建列表(),“-请选择-”)
或在ProjectVM中:
public class ProjectVM
{
public ProjectVM()
{
CategoryList = new List<SelectListItem>();
}
...
}
公共类ProjectVM
{
公共项目虚拟机()
{
CategoryList=新列表();
}
...
}
很可能导致重定向到页面时出现某种错误,并且您没有再次初始化模型的下拉列表
确保在模型的构造函数中或每次将所述模型发送到页面之前初始化下拉列表
否则,您将需要通过查看包或隐藏值帮助程序来维护下拉列表的状态 好的,海报的固定答案清楚地解释了错误发生的原因,但没有解释如何让它工作。我不确定这是否真的是一个答案,但它确实为我指明了正确的方向 我遇到了同样的问题,找到了一个巧妙的方法来解决它。我试着在这里捕捉到这一点。免责声明-我大约每年都会在网页上工作一次,而且大部分时间都不知道自己在做什么。这个答案决不能被认为是“专家”的答案,但它只做了很少的工作 假设我有一些数据对象(很可能是数据传输对象),我希望使用下拉列表为字段提供有效值,如下所示:
public class MyDataObject
{
public int id;
public string StrValue;
}
然后,ViewModel如下所示:
public class MyDataObjectVM
{
public int id;
public string StrValue;
public List<SectListItem> strValues;
}
// GET
public ActionResult Create()
{
var dataObjectVM = GetNewMyDataObjectVM();
return View(dataObjectVM); // I use T4MVC, don't you?
}
private MyDataObjectVM GetNewMyDataObjectVM(MyDataObjectVM model = null)
{
return new MyDataObjectVM
{
int id = model?.Id ?? 0,
string StrValue = model?.StrValue ?? "",
var strValues = new List<SelectListItem>
{
new SelectListItem {Text = "Select", Value = ""},
new SelectListITem {Text = "Item1", Value = "Item1"},
new SelectListItem {Text = "Item2", Value = "Item2"}
};
};
}
// POST
public ActionResult Create(FormCollection formValues)
{
var dataObject = new MyDataObject();
try
{
UpdateModel(dataObject, formValues);
AddObjectToObjectStore(dataObject);
return RedirectToAction(Actions.Index);
}
catch (Exception ex)
{
// fill in the drop-down list for the view model
var dataObjectVM = GetNewMyDataObjectVM();
ModelState.AddModelError("", ex.Message);
return View(dataObjectVM);
)
}
公共类MyDataObjectVM
{
公共int id;
公共字符串标准值;
公共列表标准值;
}
这里真正的问题,正如上面@Stephen所描述的那样,是控制器中的POST方法上没有填充选择列表。因此,控制器方法如下所示:
public class MyDataObjectVM
{
public int id;
public string StrValue;
public List<SectListItem> strValues;
}
// GET
public ActionResult Create()
{
var dataObjectVM = GetNewMyDataObjectVM();
return View(dataObjectVM); // I use T4MVC, don't you?
}
private MyDataObjectVM GetNewMyDataObjectVM(MyDataObjectVM model = null)
{
return new MyDataObjectVM
{
int id = model?.Id ?? 0,
string StrValue = model?.StrValue ?? "",
var strValues = new List<SelectListItem>
{
new SelectListItem {Text = "Select", Value = ""},
new SelectListITem {Text = "Item1", Value = "Item1"},
new SelectListItem {Text = "Item2", Value = "Item2"}
};
};
}
// POST
public ActionResult Create(FormCollection formValues)
{
var dataObject = new MyDataObject();
try
{
UpdateModel(dataObject, formValues);
AddObjectToObjectStore(dataObject);
return RedirectToAction(Actions.Index);
}
catch (Exception ex)
{
// fill in the drop-down list for the view model
var dataObjectVM = GetNewMyDataObjectVM();
ModelState.AddModelError("", ex.Message);
return View(dataObjectVM);
)
}
//获取
公共操作结果创建()
{
var dataObjectVM=GetNewMyDataObjectVM();
returnview(dataObjectVM);//我使用T4MVC,不是吗?
}
私有MyDataObjectVM GetNewMyDataObjectVM(MyDataObjectVM模型=null)
{
返回新的MyDataObjectVM
{
int id=型号?.id±0,
字符串StrValue=model?.StrValue???“”,
var strValues=新列表
{
新建SelectListItem{Text=“Select”,Value=”“},
新建SelectListITem{Text=“Item1”,Value=“Item1”},
新建SelectListItem{Text=“Item2”,Value=“Item2”}
};
};
}
//职位
公共操作结果创建(FormCollection formValues)
{
var dataObject=新的MyDataObject();
尝试
{
UpdateModel(数据对象、表单值);
AddObjectToObjectStore(数据对象);
返回重定向到操作(Actions.Index);
}
捕获(例外情况除外)
{
//填写视图模型的下拉列表
var dataObjectVM=GetNewMyDataObjectVM();
ModelState.addmodeleror(“,例如Message”);
返回视图(dataObjectVM);
)
}
这不是有效的代码,我复制/粘贴和编辑使其简单,但你明白了。如果原始数据模型和派生视图模型中的数据成员具有相同的名称,UpdateModel()可以从FormCollection值中为你填充正确的数据
我把这个贴在这里,这样当我不可避免地再次遇到这个问题时,我就能找到答案——希望它也能帮助其他人解决问题。在我的情况下,我列表中的第一个ID是零,一旦我将ID从1改为1开始,它就起作用了。@Shyju,是的,我问了并回答了它(作为社区wiki)纯粹是为了欺骗,敲打许多其他类似的问题,这些问题仍然没有得到回答或不被接受。但我看到复仇选民已经开始了——第一次是在发帖后不到2秒钟——甚至没有足够的时间阅读,更不用说答案了。我明白了。
// GET
public ActionResult Create()
{
var dataObjectVM = GetNewMyDataObjectVM();
return View(dataObjectVM); // I use T4MVC, don't you?
}
private MyDataObjectVM GetNewMyDataObjectVM(MyDataObjectVM model = null)
{
return new MyDataObjectVM
{
int id = model?.Id ?? 0,
string StrValue = model?.StrValue ?? "",
var strValues = new List<SelectListItem>
{
new SelectListItem {Text = "Select", Value = ""},
new SelectListITem {Text = "Item1", Value = "Item1"},
new SelectListItem {Text = "Item2", Value = "Item2"}
};
};
}
// POST
public ActionResult Create(FormCollection formValues)
{
var dataObject = new MyDataObject();
try
{
UpdateModel(dataObject, formValues);
AddObjectToObjectStore(dataObject);
return RedirectToAction(Actions.Index);
}
catch (Exception ex)
{
// fill in the drop-down list for the view model
var dataObjectVM = GetNewMyDataObjectVM();
ModelState.AddModelError("", ex.Message);
return View(dataObjectVM);
)
}