Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do viewmodels need keys?

Tags:

c#

asp.net-mvc

I have my view model :

namespace projInterview.Models
{
    public class QuestionViewModel
    {
        public piQuestion Question { get; set; }
        public List<piAnswer> Answers { get; set; }
        public piQuestionFavorite QuestionFavorite { get; set; }
        public piQuestionLevel QuestionLevel { get; set; }

        public QuestionViewModel(piQuestion question, List<piAnswer> answers )
        {
            Question = question;
            Answers = answers;
        }
    }
}

The VM is a standalone class. I did not scaffold this out to a controller.

In my controller:

namespace projInterview.Controllers {
    public class QuestionController : Controller
    {
        private ProjectContext db = new ProjectContext();

        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            piQuestion piquestion = db.piQuestions.Single(x => x.QuestionID == id);

            List<piAnswer> piAnswers = db.piAnswers.Where((x => x.QuestionID == id)).ToList();
            var questionViewModel = new QuestionViewModel(piquestion,piAnswers);

            return View(questionViewModel); 
        } 
}

When I get to this line:

piQuestion piquestion = db.piQuestions.Single(x => x.QuestionID == id);

I get the following error:

One or more validation errors were detected during model generation:

projInterview.DAL.QuestionViewModel: : EntityType 'QuestionViewModel' has no key defined. Define the key for this EntityType. questionViewModels: EntityType: EntitySet 'questionViewModels' is based on type 'QuestionViewModel' that has no keys defined.

piQuestion and piAnswer both have keys in the original models that the viewmodel is using. What am I doing incorrectly?

like image 651
webdad3 Avatar asked Dec 28 '13 15:12

webdad3


People also ask

What should be included in a ViewModel?

Anything that is important to the logical behavior of the application should go into the view model. Code to retrieve or manipulate data items that are to be displayed in the view through data binding should reside in the view model.

Can Viewmodels have methods?

You can have methods in your ViewModel .

Why do we need a ViewModel?

The purpose of a ViewModel is for the view to have a single object to render, alleviating the need for UI logic code in the view that would otherwise be necessary. This means the only responsibility, or concern, of the view is to render that single ViewModel object, aiding in a cleaner separation of concerns (SoC).

What is use of ViewModel in MVC?

In ASP.NET MVC, ViewModel is a class that contains the fields which are represented in the strongly-typed view. It is used to pass data from controller to strongly-typed view.


2 Answers

Wait wait wait. A view model has absolutely nothing to do with an Entity framework context. It should not be associated with it. What you seem to have right now is that db.piQuestions is an IQueryable<QuestionViewModel> which is an absolutely wrong thing to do. A view model doesn't know anything about EF and EF doesn't know anything about view models.

NEVER map your view models to any database or EF stuff. What you put as IQueryable<T> properties to your DBContext are your Domain Models. Those are the models that are bound to your database tables.

Then in your controller action you make one or more calls to your database (DbContext) in order to retrieve one or more of those domain models. Then you map (copy the properties) of those domain models to a single view model. Finally you pass the view model to the view.

Also as a side remark, view models usually have default constructors. You don't need those specific constructors taking parameters. That will just make the default model binder insane if you attempt to have such view model as parameter to a controller action.

So to conclude: view models do not have any keys. They should not even know what a key is. A key is something specific to your Data Access Layer that is to say to your Domain Models.

like image 155
Darin Dimitrov Avatar answered Oct 21 '22 19:10

Darin Dimitrov


For the sake of completion: when selecting a model in the View scaffolder, a domain model is expected, so it also pre-populates the Data context class and as such it expects a key. When selecting a viewmodel, simply delete the pre-filled DAL class and leave the DAL field blank.

View Scaffolder

If you actually define a key for a viewmodel, as I wrongly did, the scaffolder adds a definition of the viewmodel to the context class. To remedy the mess I had made, I deleted the viewmodel definitions from my context class and removed the keys from my viewmodels.

I finally got the idea from this answer.

like image 42
JDH Avatar answered Oct 21 '22 19:10

JDH