我想知道如何在Create Action上使用我的ViewModel?我尝试了几个我在论坛中找到的例子,但都没有解决我的问题。我已经绞尽脑汁待了几天,但无法弄清楚出了什么问题。
每当我点击“创建”按钮时,我都会收到以下错误: 没有为此对象定义无参数构造函数。
@model MvcMusicStore.ViewModels.AlbumViewModel
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Album</legend>
<div class="editor-label">
@Html.LabelFor(model => model.AlbumItem.GenreId, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("Genres", String.Empty)
@Html.ValidationMessageFor(model => model.AlbumItem.GenreId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.AlbumItem.ArtistId, "Artist")
</div>
<div class="editor-field">
@Html.DropDownList("Artists", String.Empty)
@Html.ValidationMessageFor(model => model.AlbumItem.ArtistId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.AlbumItem.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.AlbumItem.Title)
@Html.ValidationMessageFor(model => model.AlbumItem.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.AlbumItem.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.AlbumItem.Price)
@Html.ValidationMessageFor(model => model.AlbumItem.Price)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.AlbumItem.AlbumArtUrl)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.AlbumItem.AlbumArtUrl)
@Html.ValidationMessageFor(model => model.AlbumItem.AlbumArtUrl)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Create.cshtml
public class StoreManagerController : Controller
{
private MusicStoreDB db = new MusicStoreDB();
//
// GET: /StoreManager/Create
public ActionResult Create()
{
var viewModel = new AlbumViewModel()
{
Genres = new SelectList(db.Genres, "GenreId", "Name"),
Artists = new SelectList(db.Artists, "ArtistId", "Name")
};
return View(viewModel);
}
//
// POST: /StoreManager/Create
[HttpPost]
public ActionResult Create(AlbumViewModel vm)
{
if (ModelState.IsValid)
{
db.Albums.Add(vm.AlbumItem);
db.SaveChanges();
return RedirectToAction("Index");
}
vm.Genres = new SelectList(db.Genres, "GenreId", "Name", vm.AlbumItem.GenreId);
vm.Artists = new SelectList(db.Artists, "ArtistId", "Name", vm.AlbumItem.ArtistId);
return View(vm);
}
}
StoreManager.cs - Snippet
public class AlbumViewModel
{
public AlbumViewModel()
{
// nothing
}
public Album AlbumItem { get; set; }
public SelectList Genres { get; set; }
public SelectList Artists { get; set; }
}
public class Album
{
public Album()
{
// nothing
}
public virtual int AlbumId { get; set; }
public virtual int GenreId { get; set; }
public virtual int ArtistId { get; set; }
public virtual string Title { get; set; }
public virtual decimal Price { get; set; }
public virtual string AlbumArtUrl { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}
public class Artist
{
public Artist()
{
// nothing
}
public virtual int ArtistId { get; set; }
public virtual string Name { get; set; }
}
public class Genre
{
public Genre()
{
// nothing
}
public virtual int GenreId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual List<Album> Albums { get; set; }
}
答案 0 :(得分:28)
如果我每次看到这个问题都有镍。它通常与模型属性的命名以及如何在DropDownList
中使用它们相关。 99.999%的时间是因为人们使用Html.DropDownList()
并将其命名为与SelectList
相同。这是您应该使用强类型DropDownListFor
。
在这种情况下,您的问题是SelectList
名为Genres
和Artists
,然后在您的视图中显示:
@Html.DropDownList("Genres", String.Empty)
@Html.DropDownList("Artists", String.Empty)
见同名。
您应该做的是更改模型,以便将SelectList
命名为GenreList
和ArtistList
。然后,将视图更改为使用强类型模型。
@Html.DropDownListFor(m => m.AlbumItem.GenreID, Model.GenreList)
@Html.DropDownListFor(m => m.AlbumItem.ArtistID, Model.ArtistList)
发生这种情况的原因是您将一个名为Genres的值发布到控制器。默认模型绑定器在模型中尽职尽责地查找名为Genres的内容并实例化它。但是,它找到一个名为Genres的SelectList,而不是ID或字符串,当它试图实例化它时,它发现没有默认的构造函数。
因此你的错误。 SO充满了询问同样事情的问题。
答案 1 :(得分:0)
与Erik Funkenbusch's answer类似,我在我的表单中添加了一个DropDownList,但在我的情况下,它不是(并且不打算)提交表单,因为它是在<form></form>
标记之外:
@Html.DropDownList("myField", Model.MyField)
由于模型包含仅供显示的字段,因此也导致No parameterless constructor defined for this object
错误,因为该字段根本未提交。
在这种情况下,我通过添加排除绑定来修复它:
public ActionResult Foo(int id, int? page, [Bind(Exclude = "MyField")]MyModel model)
答案 2 :(得分:0)
对我来说问题出在BeginForm()方法本身。它看起来像这样:
@using (Html.BeginForm("MyAccount", "MyController", Model))
从另一个项目的“登录”页面复制并粘贴,该页面没有下拉列表。
无论如何,从参数列表中删除模型,一切正常:)