2
votes

While trying to scaffold a View from a ViewModel that contains fields from 2 models I need to update simultaneously, I keep getting an error that reads:

There was an error running the selected code generator: 'The entity type 'UserRegViewModel' requires a primary key to be defined.'

If I add the primary key

[Key]
public int Id { get; set; } 

to the ViewModel, a table in the DB with all the fields is created for the ViewModel, which I doubt is the correct usage of ViewModels.

My intention is to use the ViewModel to get a form from the view, and then in my controller, map each property from the VM to each of the domain models. I am successful in doing this manually (e.g. sending the ViewModel to the View, and getting the ViewModel back in the params of my HttpPost controller filled) if I leave the primary key declared, but I'm assuming I must be doing something wrong for this to be the case.

I believe I'm following all conventions (Independent folders for Models, Views, Controllers, ViewModels), and ViewModel called xxxxViewModel.cs inside the ViewModels folder.

EDIT: Full UserRegViewModel code:

using SERVICAPUY.Models.Business;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;


namespace SERVICAPUY.ViewModels
{
    public class UserRegViewModel
    {
        //[Key]
        //public int Id { get; set; }  // must be public!
                                     //public Usuario usuario { get; set; }
                                     //public IEnumerable<Prestamo> Prestamos { get; set; }

        //Usuario
        [Required(ErrorMessage = "El Nombre es obligatorio")]
        public string Nombre { get; set; }
        public string Cedula { get; set; }
        public string Direccion { get; set; }
        public string Direccion2 { get; set; }
        public string Ciudad { get; set; }
        public string Estado { get; set; }
        [Display(Name = "Código Postal")]
        public string CodPostal { get; set; }
        [Display(Name = "País")]
        public string Pais { get; set; }


        public string Telefono { get; set; }
        [DataType(DataType.Date)]
        public DateTime? FechaNacimiento { get; set; }

        //Prestamo
        public Auto auto { get; set; }

        [Required(ErrorMessage = "Cuántas cuotas son?")]
        [Range(1, 120, ErrorMessage = "El número de cuotas debe ser entre 1 y 120.")]
        public int Cuotas { get; set; }
        [Required(ErrorMessage = "Cuál es el monto del préstamo?")]
        public double Monto { get; set; }
        [Required(ErrorMessage = "Cuál es el interés?")]
        [Display(Name = "Interés")]
        public double? Interes { get; set; }
        [Required(ErrorMessage = "Qué día del mes le toca al usuario hacer el pago?")]
        [Display(Name = "Día de Pago")]
        [Range(1, 31, ErrorMessage = "El día de pago corresponde a día del mes.")]
        public int? DiaDePago { get; set; }
        [Display(Name ="Tipo de Prestamo")]
        public tipoPrestamo tipoPrestamo { get; set; }
        public Estatus Estatus { get; set; }
    }
}
1
Viewmodel should NOT be an entity. Please share your full .cs of the UserRegViewModel.Ziv Weissman
I suppose you are using the same class for the viewmodel and the persistence. Viewmodels are DTOs, which should serve this only purpose. Yes, a DTO will have lot of fields common with one or many persistence model classes, but you can use automapper for example to map between the two sides cleanly in both directions.ZorgoZ
@ZivWeissman, totally agree! I could use the ViewModel perfectly, but I'm asking to learn and make sure I'm following best practices. Will edit the Q to include the code you requestdcaping
@ZorgoZ, I'm not sure what you mean. What do you mean by "using the same class"? I have created a class for each domain model, and a separate class as shown in the edit just for the ViewModel. (I will look further into the automapper, but I'm not sure if this is my issue)dcaping
I'm less familiar with MVC Core, but it looks to me that somewhere you defined this class as data context class. Can you check maybe do something like this vid: youtube.com/watch?v=T2R8tA80ZuEZiv Weissman

1 Answers

2
votes

@ZivWeissman found the answer. It's in the comments. There was a reference in the DbContext class to the ViewModel. Maybe that raises another question since I'm positive I didn't add the reference in there, but for now, the issue is resolved.