2012-10-03 12 views
8

Chciałbym wiedzieć, w jaki sposób mogę użyć mojego ViewModel w Create Action? Próbowałem kilku przykładów, które znalazłem na forum, ale żaden nie rozwiązał mojego problemu. Odkładałem mózg na kilka dni, ale nie wiem, co jest nie tak.Błąd ViewModel MVC - Dla tego obiektu nie zdefiniowano konstruktora bez parametrów

Po każdym kliknięciu przycisku Utwórz pojawia się następujący błąd: Dla tego obiektu nie zdefiniowano konstruktora bez parametrów.

@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 - Fragment

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

Co to jest "gatunek"? – SLaks

+0

Dodano "Gatunek" i "Artysta" na powyższym kodzie. – fvss

+0

Jedyne, co wydaje się nie mieć konstruktora bez parametrów, to SelectList (http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.108).aspx). Co jeśli to skomentujesz? –

Odpowiedz

24

Gdybym miał niklu za każdym razem widziałem tego problemu. Zazwyczaj jest to związane z nazwami właściwości twojego modelu i sposobem ich użycia w DropDownList. 99,999% czasu jest, ponieważ ludzie używają Html.DropDownList() i nazywają to samo, co ich SelectList. Jest to jeden z powodów, dla którego powinieneś używać silnie wpisanego DropDownListFor.

W tym przypadku problem jest to, że masz SelectList s nazwanych Genres i Artists, a następnie w widoku masz:

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

widać, samą nazwę.

Należy zmienić model, aby SelectList miały nazwy: Następnie zmień swój widok, aby używać mocno wpisanego modelu.

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

Dzieje się tak dlatego, że publikujesz do kontrolera wartość o nazwie Genres. Domyślny segregator modelu posłusznie wyszukuje w modelu, aby znaleźć coś o nazwie Gatunki i utworzyć instancję. Ale zamiast identyfikatora lub ciągu znaków znajduje listę SelectList o nazwie Gatunki, a kiedy próbuje ją utworzyć, stwierdza, że ​​nie ma domyślnego konstruktora.

Twój błąd. SO jest wypełnione pytaniami o to samo.

+0

To wszystko! Dziękuję Ci! – fvss

+0

To samo tutaj. Uratowałeś moje kilka godzin –

0

podobne do Erik Funkenbusch's answer bym dodał DropDownList do mojej postaci, jednak w moim przypadku nie było (i nie miało być) złożony z postaci, jak to było poza <form></form> tagi:

@Html.DropDownList("myField", Model.MyField) 

Ponieważ model zawierał tylko pole do wyświetlenia, spowodował on również błąd No parameterless constructor defined for this object, ponieważ pole w ogóle nie zostało przesłane.

W tym przypadku stałe go dodając wyklucza wiązanie:

public ActionResult Foo(int id, int? page, [Bind(Exclude = "MyField")]MyModel model) 
0

Dla mnie problemem było w sposób sam BeginForm(). Wyglądało to tak:

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

Skopiowano i wklejono ze strony logowania innego projektu, która nie ma listy rozwijanej.

W każdym razie, usuń Model z listy parametrów i wszystko działa dobrze :)

Powiązane problemy