2012-10-03 92 views
8

Me gustaría saber cómo puedo usar mi ViewModel en Create Action? Probé varios ejemplos que encontré aquí en el foro, pero ninguno resolvió mi problema. He estado trabajando en mi cerebro por unos días, pero no puedo descifrar qué está mal.MVC ViewModel Error - No se ha definido ningún constructor sin parámetros para este objeto

Cada vez que hago clic en el botón Crear, aparece el siguiente error: No se ha definido ningún constructor sin parámetros para este objeto.

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

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

¿Qué es 'Género'? – SLaks

+0

Se agregó 'Género' y' Artista' en el código anterior. – fvss

+0

Lo único que parece no tener un constructor sin parámetros es SelectList (http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.108).aspx). ¿Qué pasa si comenta eso? –

Respuesta

24

Si tuviera un centavo por cada vez que he visto este problema. Por lo general, está relacionado con el nombre de las propiedades de su modelo y cómo las usa en un DropDownList. 99.999% del tiempo es porque la gente está usando Html.DropDownList() y nombrándolo igual que su SelectList. Esta es una de las razones por las que debe usar el DropDownListFor fuertemente tipado.

En este caso, el problema es que usted tiene SelectList s nombrados Genres y Artists, a continuación, en su opinión tiene:

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

Sede, mismo nombre.

Lo que debe hacer es cambiar su modelo para que el SelectList s se denomine GenreList y ArtistList. Luego, cambie su vista para usar un modelo fuertemente tipado.

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

La razón por la que esto sucede es porque está publicando un valor denominado Géneros en el controlador. La carpeta de modelo predeterminada busca diligentemente en el modelo para encontrar algo llamado Géneros y crear una instancia. Pero, en lugar de una ID o una cadena, encuentra una lista de selección llamada Géneros, y cuando intenta crear una instancia, descubre que no hay un constructor predeterminado.

Por lo tanto, su error. SO está lleno de preguntas sobre este tema.

+0

¡Eso es todo! ¡Gracias! – fvss

+0

Lo mismo aquí. Me salvaste varias horas –

0

similares a Erik Funkenbusch's answer me había añadido un DropDownList a mi forma, sin embargo, en mi caso no fue (y no estaba destinado a ser), presentado con el formulario ya que estaba fuera de las etiquetas: <form></form>

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

Como el Modelo solo contenía el campo para mostrar, esto también causó el error No parameterless constructor defined for this object porque el campo no se envió.

En este caso me fijo mediante la adición de una unión excluyen:

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

Para mí el problema estaba en el método BeginForm() en sí. Se veía así:

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

Copiado y pegado desde la página de inicio de sesión de otro proyecto, que no tiene un menú desplegable.

De todos modos, elimine el modelo de la lista de parámetros y todo funciona perfectamente :)

Cuestiones relacionadas