Reputation: 2817
I want to pass some data from my view to my controller, my view looks like this:
<div id="Section1" class="divFiles">
<span>Section 1 </span>
<input type="text" name="test[0]">
<input type="text" name="test[1]">
<input type="text" name="test[2]">
<input type="text" name="test[3]">
</div>
<div id="Section2" class="divFiles">
<span>Section 2 </span>
<input type="text" name="test[4]">
<input type="text" name="test[5]">
<input type="text" name="test[6]">
<input type="text" name="test[7]">
</div>
But this way I'm just sending a list of strings to my controller, there are not keys and I need key because I need this to be grouped by keys.
I would like to pass my data like a Dictionary
, grouped by sections, for example:
Section 1: {"first string", "second string", "third string"},
Section 2: {"fourth string", "fifth string"}
and like that,I'm thinking that the best way to do this probably is sending the data as a Dictionary
of type Dictionary<string, List<string>>
where Section 1
, Section 2
would be the keys
and then the list of string their values
, how could I do that? I can use JQuery for that purpose too, but I'm not sure of how I must write the html to send the data like that. Doing it this way my parameter in my controller action should be of type Dictionary<string, List<string>>
Any suggestions of doing this in a different way is welcome too
Upvotes: 0
Views: 4733
Reputation:
For all but a simple Dictionary
where both the Key
and Value
are value types (for example Dictionary<string, int>
), the DefaultModelBinder
requires that the control names be in the following format (in your case, assuming the POST method signature is public ActionResult XX(Dictionary<string, List<string>> names)
)
<input name="names[0].Key" value="aaa" ... />
<input name="names[0].Value[0]" value="bbb" ... />
<input name="names[0].Value[1]" value="ccc" ... />
<input name="names[1].Key" value="xxx" ... />
<input name="names[1].Value[0]" value="yyy" ... />
<input name="names[1].Value[1]" value="zzz" ... />
There are no HtmlHelper
extension methods that can generate the correct name
attributes for a Dictionary
containing either a Key
and/or a Value
that is a complex object or collection,which means that you would need to generate all the html manually and lose all the benefits of strong types binding, client side validation etc.
It would be far easier to create a view model representing your structure, for example
public class ValueVM
{
public string Name { get; set; }
}
public class GroupVM
{
public string Key { get; set; }
public List<ValueVM> Values { get; set; }
}
and then in the GET method initialize a collection of GroupVM
, populated with data and pass it to the view, for example
var model = new List<GroupVM>
{
new GroupVM
{
Key = "Section 1",
Values = new List<ValueVM>
{
new ValueVM { Name = "...." },
new ValueVM { Name = "...." }
}
},
new GroupVM
{
Key = "Section 2",
....
}
};
return View(model);
Then in the view
@model List<GroupVM>
....
@using (Html.BeginForm())
{
@for(int i = 0; i < Model.Count; i++)
{
<div>
<h2>@Model[i].Key</h2>
@Html.HiddenFor(m => m[i].Key)
@for (int j = 0; j < Model[i].Values.Count; j++)
{
@Html.TextBoxFor(m => m[i].Values[j].Name)
}
</div>
}
....
}
And the POST method signature would be
public ActionResult XXXX(List<GroupVM> model)
Upvotes: 3
Reputation: 11478
You should create an object, then pass the object to your Controller. It will be far easier, otherwise you'll have a Controller with a massive set of parameters performing a form submission. I would use JavaScript, then simply do an Ajax request.
public class Example
{
public int Id { get; set; }
public string Key { get; set; } // Bad name
public string Value { get; set; } // Bad name
}
So your Controller would expect, Example.
public IActionResult Submit(List<Example> examples)
{
// Collection of our inputs as an object, manipulate.
}
Then for the JavaScript, you would simply do:
function getFormDataAndCreateObject() {
var formElements = $('[data-rel="section"]');
var elements = [];
$.each(formElements, function (index) {
elements.push(buildExample(index, formElements[index].attr('name'), formElements[index].value));
});
// Either return elements, or simply perform Ajax to send to controller.
}
function buildExample(id, section, name) {
var examples = [{
Id : id,
Section: section,
Name: name
}];
}
May have typos, but the concept is what is important.
Upvotes: 2