0

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

1
  • Create an object with an array of strings and a name property (for section) . Then create an array of one or more of those objects. Do this in javascript. Then create a similar class in c#. Your controller should take an array or a list of them. Send it as json to your controller. Commented May 9, 2017 at 23:04

2 Answers 2

3

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)
Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.