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]));
})