2012-10-03 70 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)) 

從另一個項目的登錄頁面複製並粘貼,該頁面沒有下拉框。

無論如何,從參數列表中刪除模型,它一切正常:)

相關問題