Using the razor syntax in asp.net mvc makes it easy to show arrays in a view, and if you want to do an array model binding, you will experience an index fracture problem, as shown in the following example:
<input type= "Text" Name= "[0]. Name "/>
<input type=" text "Name=" [1]. Name "/>
<input type=" text "Name=" [2]. Name "/>
<input type=" text "Name=" [4]. Name "/>
<input type=" text "Name=" [5]. Name "/>
The array name breaks at index 3 and discards the following 4 and 5 after the model-binder resolution completes, and only 0, 1, 2 are correctly parsed into the corresponding model.
This fault occurs frequently in the event of a dynamic array binding.
The following is a case study of how to do dynamic array binding. Suppose the following scenarios are applied:
Requires the ability to dynamically add and remove an opportunity, and then the opportunity to populate the form with a single array or collection property in the view model to facilitate subsequent business processing.
Way one: Use placeholder replacements
The first way I call it "placeholder replacement" is to use the ASP.net MVC default model binder (Defaultmodelbinder) and combine front-end processing.
First, the first step is to design the view model based on the business scenario:
public class Ordermodel
{
///<summary>
///flight number
///</summary> public
string Flightno {get; set;}
<summary>
///
///</summary> public
list<passenger> passengers {get; set;}
} Public
class passenger
{public
string Name {get; set;}
public string Idno {get; set;}
}
Second, this view model is passed to the view:
Public ActionResult New ()
{
Models.ordermodel Ordermodel = new Models.ordermodel ();
list<models.passenger> passenger = new list<models.passenger> ();
Passenger. ADD (New Models.passenger ());
Ordermodel.passengers = passenger;
Return View (Ordermodel);
}
and show it in the view file:
<div style= "width:680px" > <div class= "form-group" > <label> flight </label><br/> @ Html.textboxfor (P => p.flightno, new {placeholder = "flight Number"}) </div> <div class= "Form-group" > <label& GT, Flight </label> <table class= "Passenger" > <tbody> @if (model.passengers!= null && MODEL.PA Ssengers. Count > 0) {for (int i = 0; i < Model.Passengers.Count i++) {<tr> <td> name:</td> ;td> @Html. Textboxfor (P => model.passengers[i). Name) </td> <td> ID number:</td> <td> @Html. Textboxfor (P => model.passengers[i). Idno) </td> <td> <a href= "javascript:;" onclick= "Removepassenger (This)" > Delete </a> </td > </tr>} </tbody> </table> <div style= "margin-top:10px" > <a href= "Javascrip
T:; "onclick=" Addpassenger () > Add Flight </a> </div> </div> </div>
Because the model binder for ASP.net mvc (Defaultmodelbinder) has the ability to automatically parse shapes such as "[0]. Property name", "[1]. Property name", the array subscript can be represented as a placeholder in the template file:
<!--opportunity template-->
<script type= "text/html" id= "passengertemplate" >
<tr>
<td> Name: </td>
<td><input id= "Passengers_{}__name" Name= "passengers[{}". Name "type=" text "value=" "></td>
<td> ID number:</td>
<td><input id=" passengers_{ }__idno "Name=" passengers[{}]. Idno "type=" text "value=" "></td>
<td>
<a href=" javascript:; "onclick=" Removepassenger ( This) "> delete </a>
</td>
</tr>
</script>
"{}" in the above code is an array subscript placeholder. When you add an opportunity, you can calculate the number of people who already have an opportunity, and then use JavaScript to replace "{}" as an array subscript.
Add Flight person
function Addpassenger () {
///Current add row array element subscript
var index = $ (". Passenger"). Find ("Tbody"). Find ("tr"). length;
{} is an array element subscript placeholder
var passengerhtml = $ (' #passengerTemplate '). html (). Replace (/{}/g, index);
$ (". Passenger"). Find ("Tbody"). Append (passengerhtml);
When deleting an opportunity, note that if the deletion is not the last one, an index fracture problem will occur and the array subscript needs to be readjusted:
Remove Flight person
function Removepassenger (e) {
$ (E). Parents ("tr"). Remove ();
Iterate through each row of the table, rearrange the array subscript
var TB = $ (". Passenger").
var count = Tb.find ("Tbody"). Find ("tr"). Length;
for (var i = 0; i < count; i++) {
var newtr = Tb.find ("tr"). EQ (i) formhtml (). Replace (/\[\d+\]/g, ' [' + i + '] '); Resizes the array element subscript
tb.find ("tr"). EQ (i). html (NEWTR);
}
This way, when we submit the form, the flight information is automatically populated into the passengers property of the model.
Mode two: Using Vue.js
using the first method requires writing a large number of front-end code, including template files, adding deletion events, as well as dealing with interpolation problems in the order of readjustment.
If you use the front-end MVVM framework will make this process simple, the current more popular front-end MVVM framework has ANGULARJS, there are antique knockoutjs, there are emerging niche framework vue.js.
Angularjs relatively large, such a simple model binding with anuglar have a sense of overkill; knockout and Vue are lightweight MVVM frameworks, but knockout need to wrap native data to make observable objects, Value and assignment need to take the form of function call, not very convenient to use, so I chose the vue.js. Vue.js is a lightweight and efficient library that does not have the API like angular module, controller, scope, factory, service, which is the core of a model binding function. Only the size of the 70kb,gzip compressed only 25kb, very lightweight.
The rationale for this approach is that the front end uses Vue.js to declare the view model and bind it, then serialize the model into a JSON string when submitting the form to the background, and then deserialize the json.net into a C # object in the background.
Because of the binding characteristics of vue.js, we only need to manipulate the array elements, without extra attention to DOM operations, save a lot of work.
First, you need to declare the view model and bind using Vue.js:
<script src= "~/scripts/vue.js" ></script> <script type= "Text/javascript" > View model var ViewModel = {flightno: ', passengers: [{elementid: ' passenger_1 ', Name: ', Idno: '}]}//modulo Type binding new Vue ({el: ' #app ', Data:viewmodel, methods: {removepassenger:function (ElementID) {for (var i = 0; i < viewModel.Passengers.length; i++) {if (Viewmodel.passengers[i].
ElementID = = ElementID) {ViewModel.Passengers.splice (I, 1);
}}, Addpassenger:function () {var TB = document.getelementsbytagname (' table ') [0];
var index = tb.rows[tb.rows.length-1].getelementsbytagname (' input ') [0].getattribute ("id"). split ('_') [1];
ViewModel.Passengers.push ({Name: ', Idno: ', ElementID: ' Passenger_ ' + (index + 1)});
}, Submitform:function () {var jsonstring = json.stringify (ViewModel);
document.getElementById ("ViewModel"). Value = jsonstring;
return true;
}
}
}); </script>
Then use the vue.js binding in the view:
<form action= "/order2/newpost" method= "POST" > <div id= "App" style= "width:680px" > <div class= " Form-group "> <label> flight </label><br/> <input v-model=" Flightno "type=" text "placeholder=" Flight number " /> </div> <div class= "Form-group" > <label> flight </label> <table class= "Passenger" > & lt;tbody> <tr v-for= "passenger in Passengers" > <td> name:</td> <td><input v-model= "pas Senger. Name "V-bind:id=" passenger. ElementID "type=" text "/></td> <td> ID number:</td> <td><input v-model=" passenger. Idno "type=" text "/></td> <td> <a href=" javascript:; "v-on:click=" Removepassenger (passenger. ElementID) "> Delete </a> </td> </tr> </tbody> </table> <div style=" margin-top:10 px "> <a href=" javascript:; "v-on:click=" Addpassenger "> Add Flight Person </a> </div> <div style=" margin-to p:10px ">; input type= "Submit" class= "btn Btn-default" v-on:click= "SubmitForm"/> </div> </div> </div> ; input type= "hidden" id= "ViewModel" name= "ViewModel"/> </form>
Finally, in controller, we can deserialize the corresponding C # strongly typed model:
[HttpPost]
Public ActionResult Newpost ()
{
var jsonstring = request.form["ViewModel"];
Models.ordermodel model = newtonsoft.json.jsonconvert.deserializeobject<models.ordermodel> (jsonString);
if (model!= null) {
//We code here ...
}
Return redirecttoaction ("Index", "Home");
}
These two methods can be implemented dynamic array binding, the way to use JS for placeholder replacement, the elements of the form are named [index]. Property name, and then the default model of MVC to transform the model binding device;
Mode two uses Vue.js to directly model binding, serializing the model as a JSON string when submitting the form, and then deserializing the back end, resulting in a strongly typed model.
The above is the entire content of this article, I hope to help you learn.