In the Publish field, the SelectList.SelectedValue drop-down list is null

My model is as follows:

public class testCreateModel { public string s1 { get; set; } public SelectList DL { get; set; } public testCreateModel() { Dictionary<string, string> items = new Dictionary<string, string>(); items.Add("1", "Item 1"); items.Add("2", "Item 2"); DL = new SelectList(items, "Key", "Value"); } } 

My initiating actions:

  public ActionResult testCreate() { testCreateModel model = new testCreateModel(); return View(model); } 

My Razor view (unnecessary parts removed):

 @model Tasks.Models.testCreateModel @using (Html.BeginForm()) { <fieldset> <legend>testCreateModel</legend> <div class="editor-label"> @Html.LabelFor(model => model.s1) </div> <div class="editor-field"> @Html.EditorFor(model => model.s1) </div> <div class="editor-label"> Select an item: </div> <div class="editor-field"> @Html.DropDownList("dropdownlist", (SelectList)Model.DL) </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } 

Reverse Copy Action:

  public ActionResult testCreate(testCreateModel model, FormCollection collection) { if (ModelState.IsValid) { Console.WriteLine("SelectedValue: ",model.DL.SelectedValue); Console.WriteLine("FormCollection:", collection["dropdownlist"]); // update database here... } return View(model); } 

In post back, model.DL.SelectedValue is null. (However, the selected item can be obtained from FormCollection, but this does not apply to the point). The DL object is still populating properly, the Immediate Window is displayed as follows:

 model.DL {System.Web.Mvc.SelectList} base {System.Web.Mvc.MultiSelectList}: {System.Web.Mvc.SelectList} SelectedValue: null model.DL.Items Count = 2 [0]: {[1, Item 1]} [1]: {[2, Item 2]} model.DL.SelectedValue null 

Q1: How can I use the SelectedValue property instead?

Now, if in the Razor view, I change the name of the Html SELECT tag to DL (the same as the name of the property in the model):

 @Html.DropDownList("DL", (SelectList)Model.DL) 

I get an exception:

 No parameterless constructor defined for this object. Stack Trace: [MissingMethodException: No parameterless constructor defined for this object.] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 System.Activator.CreateInstance(Type type, Boolean nonPublic) +69 System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +199 System.Web.Mvc.DefaultModelBinder.BindSimpleModel(ControllerContext controllerContext, ModelBindingContext bindingContext, ValueProviderResult ... 

Q2: Why?

Thanks.

+6
source share
2 answers

MVC will only return the value of the selected parameter in your POST, so you need a property to have one return value.

As a good tip, try installing SelectLists through the ViewBag, which helps keep your ViewModels clean from the data that should fill out the form.

So your example can be solved as follows:

 public class testCreateModel { public string s1 { get; set; } public int SelectedValue { get; set; } } 

and in your view just do this:

 @Html.DropDownList("SelectedValue", (SelectList)ViewBag.DL) 

before populating ViewBag.DL in GET action.

As with your Q2, ModelBinder by default requires that all types for the binding have a default constructor (so that ModelBinder can create them)

+11
source

The answer has been chosen, but look how I did it. Below is the code, as I usually do this when populating the dropdown list. This is very simplistic, I suggest you use it as a basis for creating your falls.

At the top of my view, I indicate my view model:

 @model MyProject.ViewModels.MyViewModel 

In my view, I have a drop-down list that displays all the banks that the user can choose from:

 <table> <tr> <td><b>Bank:</b></td> <td> @Html.DropDownListFor( x => x.BankId, new SelectList(Model.Banks, "Id", "Name", Model.BankId), "-- Select --" ) @Html.ValidationMessageFor(x => x.BankId) </td> </tr> </table> 

I always have a view model for the view, I never pass the domain object directly to the view. In this case, my view model will contain a list of banks that will be populated from the database:

 public class MyViewModel { // Other properties public int BankId { get; set; } public IEnumerable<Bank> Banks { get; set; } } 

My banking domain model:

 public class Bank { public int Id { get; set; } public string Name { get; set; } } 

Then, in my action method, I instantiate my view model and populate the list of banks from the database. Once this is done, I will return the view model to the view:

 public ActionResult MyActionMethod() { MyViewModel viewModel = new ViewModel { // Database call to get all the banks // GetAll returns a list of Bank objects Banks = bankService.GetAll() }; return View(viewModel); } [HttpPost] public ActionResult MyActionMethod(MyViewModel viewModel) { // If you have selected an item then BankId would have a value in it } 

Hope this helps.

+10
source

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


All Articles