How to bind selected list using viewmodel?

I cannot get a select list to bind to my ViewModel.

I have a ViewModel that contains a Question object and a string

public class QuestionViewModel { public Question Question { get; set; } public string RefUrl { get; set; } public QuestionViewModel() { } public QuestionViewModel(Question question, string RefUrl) { this.Question = question; this.RefUrl = RefUrl; } public QuestionViewModel(Question question) { this.Question = question; this.RefUrl = ""; } } 

this is the controller:

 public ActionResult Edit(int id) { Question question = db.Question.Single(q => q.question_id == id); QuestionViewModel qvm = new QuestionViewModel(question); ViewBag.category_id = new SelectList(db.Category, "category_id", "category_name", qvm.Question.category_id); ViewBag.type_code = new SelectList(db.Question_Type, "type_code", "type_description", qvm.Question.type_code); return View(qvm); } 

and the code in my view is as follows:

 <div class="editor-label"> @Html.LabelFor(model => model.Question.type_code, "Question_Type") </div> <div class="editor-field"> @Html.DropDownListFor(model => Model.Question.Question_Type, (SelectList)ViewBag.type_code) @Html.ValidationMessageFor(model => model.Question.type_code) </div> 

The Question QuestionType object is set in the view for the selected value, but when I submit the form, ValidationMessageFor triggers

+6
source share
1 answer

You have no view model . This is a hybrid class that you called the view model and in which you wrapped the domain object ( Question ). This is bad, do not do it.

Here I would recommend you. Start by developing a real presentation model that will reflect the requirements of your presentation (from your current description, this is a drop-down list containing some types of questions and allowing the user to select some type of question from this ddl):

 public class QuestionViewModel { [DisplayName("Question_Type")] public string SelectedQuestionType { get; set; } public IEnumerable<SelectListItem> QuestionTypes { get; set; } // didn't see where you are using this on your view public string RefUrl { get; set; } } 

then map the controller card between your domain model and the view model. Of course, a further improvement will be to use AutoMapper to avoid this mapping across all actions of your controller:

 public ActionResult Edit(int id) { var question = db.Question.Single(q => q.question_id == id); var qvm = new QuestionViewModel { // preselect a value SelectedQuestionType = question.type_code, QuestionTypes = db.Question_Type.Select(x => new SelectListItem { Value = x.type_code, Text = x.type_description }) }; return View(qvm); } 

and then:

 <div class="editor-label"> @Html.LabelFor(x => x.SelectedQuestionType) </div> <div class="editor-field"> @Html.DropDownListFor( x => SelectedQuestionType, new SelectList(Model.QuestionTypes, "Value", "Text") ) @Html.ValidationMessageFor(x => x.SelectedQuestionType) </div> 

ViewBag/ViewData final note: make sure you get rid of any ViewBag/ViewData and put everything you need in your view model. You showed some categories in the action of your controller that were not implemented in the shown fragment of the view. If you ever needed them, just put them in your look model, just as we did with the types of questions.

+14
source

Source: https://habr.com/ru/post/892313/


All Articles