Model Binding an Array from a Form Post | Asp.Net MVC & Asp.Net Core

if you form post html form fields:

<li>
  <label for="name">Your name<span>*</span></label>
  <input type="text" id="name" name="Name" />
</li>
<li>
  <label for="phoneNumber">Telephone<span>*</span></label>
  <input type="tel" id="phoneNumber" name="PhoneNumber" />
</li>

to a Controller using the [FromForm] attribute, AspNet will modelbind the form fields to your parameters by matching the name= attribute of the input elements to Property names on the parameter class:

class MyController : Controller
{
    public IActionResult Index([FromForm]Contact contact){ ... }
}

// ----
public class Contact
{
    public string Name {get;set;}
    public string PhoneNumber {get;set;}
}

But what about model binding an array — for instance, if you have a list of question inputs, and want to store the answers in a list?

If you name each field as if it were an array element:

 <fieldset id="q1">
     <label class="question">Question 1</label>
     <ul class="form-style">
        <li>
            <input type="radio" id="c1" name="answers[0]" value="@c1"/>
            <label for="c1">@c1</label>
        </li>
        <li>
            <input type="radio" id="c2" name="answers[0]" value="@c2"/>
            <label for="c2">@c2</label>
        </li>
    </ul>
  </fieldset>
    <fieldset id="q2">
        <label class="question">Question 1?</label>
        <ul class="form-style">
            <li>
                <input type="radio" id="b1" name="answers[1]" value="@b1"/>
                <label for="b1">@b1</label>
            </li>
            <li>
                <input type="radio" id="b2" name="answers[1]" value="@b2"/>
                <label for="b2">@b2</label>
            </li>
            <li>
                <input type="radio" id="b3" name="answers[1]" value="@b3"/>
                <label for="b3">@b3</label>
            </li>
            <li>
                <input type="radio" id="b4" name="answers[1]" value="@b4"/>
                <label for="b4">@b4</label>
            </li>
        </ul>
    </fieldset>

then AspNet will bind the submitted fields named answers[0], answers[1], ... to an array Property in your class with the matching name:

public class Questions
{
    public string[] Answers {get;set;}
}

.Net Core Strong Typed Configuration Binding for Arrays | Microsoft.Extensions.Configuration

The .Net Core Microsoft.Extensions.Configuration package includes the ConfigurationBinder.Get<>() method which can read a config file and bind name-value entries to a class. This gives you strongly typed configuration:

public class FromTo
{
    public string From { get; init; }
    public string To { get; init; }
}

The method is an extension method for Configuration so you can call it straight off a Configuration instance. In an Asp.Net Startup.cs class, for instance:

services.AddSingleton(
    s=>Configuration
            .GetSection("fromto").Get<FromTo>());

will result in your services collection knowing to provide an FromTo class with the Properties populated from the configuration entries, matched by section:propertyname :

{
  "fromto:from": "[email protected]",
  "fromto:to": "[email protected]"
}

or if you use secrets:

cd <projectdirectory>
dotnet user-secrets init
dotnet user-secrets set fromto:from [email protected]
dotnet user-secrets set fromto:to [email protected]

That works great for the usual primitives - string, numbers, boolean — but what about binding an Array?

public class FromTo
{
    public string From { get; init; }
    public string To[] { get; init; }
}

the From field is still bound but the To field silently fails and results in a null value.

The magic trick is to add a colon-separated number suffix to each setting name:

{
  "fromto:from": "[email protected]",
  "fromto:to:0": "[email protected]",
  "fromto:to:1": "[email protected]",
  "fromto:to:2": "[email protected]",
}

Now Configuration.GetSection("fromto").Get<FromTo>() will successfully bind all 3 rows for "fromto:to into the public string To[] array.