2012-10-03 54 views
8

我想知道如何在Create Action上使用我的ViewModel?我在论坛中发现了几个例子,但没有解决我的问题。我已经花了我的脑子几天,但无法弄清楚什么是错的。MVC 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 - 摘录

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; } 
    } 
+1

什么是流派? – SLaks

+0

在上面的代码中添加了“流派”和“艺术家”。 – fvss

+0

似乎没有无参数构造函数的唯一东西是SelectList(http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.108).aspx)。如果你评论这些呢? –

回答

24

如果我假如每次我看到这个问题时镍。它通常与您的模型属性的命名以及如何在DropDownList中使用它们相关。 99.999%的时间是因为人们使用Html.DropDownList()并将其命名为SelectList。这是您应该使用强类型DropDownListFor的原因之一。

在这种情况下,你的问题是,你有SelectList的named GenresArtists,那么在你看来,你有:

@Html.DropDownList("Genres", String.Empty) 
@Html.DropDownList("Artists", String.Empty) 

见,相同的名称。

你应该做的是改变你的模型,使SelectList被命名为GenreListArtistList。然后,将您的视图更改为使用强类型模型。

@Html.DropDownListFor(m => m.AlbumItem.GenreID, Model.GenreList) 
@Html.DropDownListFor(m => m.AlbumItem.ArtistID, Model.ArtistList) 

发生这种情况的原因是您要将名为Genres的值发布到控制器。默认模型联编程序忠实地在模型中查找以查找称为流派的东西并实例化它。但是,它不是一个ID或字符串,而是找到一个名为Genres的SelectList,当它试图实例化它时,它发现没有默认构造函数。

因此你的错误。这个问题充满了关于这个问题的问题。

+0

抛出的错误!谢谢! – fvss

+0

同样在这里。你救了我几个小时 –

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) 
0

对我来说,问题是在BeginForm()方法本身。它看起来像这样:

@using (Html.BeginForm("MyAccount", "MyController", Model)) 

从另一个项目的登录页面复制并粘贴,该页面没有下拉框。

无论如何,从参数列表中删除模型,它一切正常:)

相关问题