Home > Back-end >  Submit object contained within DropDownList selected value
Submit object contained within DropDownList selected value

Time:08-27

I'm stuck with this ASP.NET MVC 5 issue. I have implemented a razor view which contains a DropDownList control that is populated with objects set as values using javascript. This is the function that achieves such task:

    function populateFilings(keyValueArray) {   
    
        var dropDown = document.getElementById('myDropDown');
    
        keyValueArray.forEach(function (item) {
            dropDown.options.add(new Option(item.Key, JSON.stringify(item.Value)));
        });
    }

The DropDownList is as follows (nothing really special here):

@Html.DropDownList("myDropDown", Enumerable.Empty<SelectListItem>(), new { @class = "form-control" })

The created select options have this appearance:

<option value="{"FileName":"20220511T171503750.zip","FilingID":60,"BatchID":41,"FormTypeID":2,"SnapshotID":12}">Option 1</option>

And once the form is submitted, the following Controller method is executed:

        [HttpPost]
        public ActionResult Index(IndexViewModel model)
        {
            //not relevant code here
        }

The view model implementation is quite simple as well:

namespace ViewModels
{
    public class IndexViewModel
    {
        //Many not relevant properties

        public FilingBatch myDropDown { get; set; }
    }
}

And finally, the class that should contain the data placed in the DropDownList is implemented as follows:

    public class FilingBatch
    {
        public string FileName { get; set; }
        public int FilingID { get; set; }
        public int BatchID { get; set; }
        public int FormTypeID { get; set; }
        public int SnapshotID { get; set; }
    }

But the "myDropDown" property within the ViewModel is always null rather than containing an object populated with the values contained within the DropDownList. How can I fix this? What am I missing?

CodePudding user response:

SelectList is a name/value (or better said as key/value perhaps) pair for each one. Important here is the "value" you have set. You will want to set these values as strings.

You probably want these:

<option value="{"FileName":"20220511T171503750.zip","FilingID":60,"BatchID":41,"FormTypeID":2,"S`napshotID":12}">Option 1</option>

to appear like (note the single quotes)

<option value='{"FileName":"20220511T171503750.zip","FilingID":60,"BatchID":41,"FormTypeID":2,"SnapshotID":12}'>Option 1</option>

In your model then set those as a string type and not a FilingBatch type. Then in your post back method where you have //not relevant code here you will want de-serialize that string into the FilingBatch type.

Try a strong type using a DropDownListFor https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.html.selectextensions.dropdownlistfor?view=aspnet-mvc-5.2

@Html.DropDownListFor(m => m.myDropDown, 
        new SelectList(Enumerable.Empty<SelectListItem>()), 
        new { @class = "form-control" })

As an aside try to work the property name myDropDown and prefer model property names to be like MyDropDown in your IndexViewModel or a better name to illustrate purpose for example SelectedFilingBatch, SerializedFilingBatch or some such.

Example

public string SerializedFilingBatch { get; set; }

Partial example

 FilingBatch? filingBatch = 
                JsonSerializer.Deserialize<FilingBatch>(model.SerializedFilingBatch);

CodePudding user response:

if content type is application/x-www-form-urlencoded, post data should be like :

Name : "Foo", 
Address.City : "NYC",
Adress.Line1 : "Line1"

if it is application/json, should be:

{
  Name : "Foo",
  Address : {
     City: "NYC",
     Line1 : "Line1"
   }
}

Solution:

In this case, content-type is form. formdata should be modify before form submit. this could do with 'formdata' event.

formElemet.addEventListener("formdata",(e) => {
     var dropdown = document.getElementById("myDropDown");
     const formData = e.formData;
     Object.entries(JSON.parse(dropdown.value))
                 .map((item) => 
                     formData.append(`myDropDown.${item[0]}`,item[1]));
})
  • Related