Skip to content Skip to sidebar Skip to footer

Mvc Core Add Multiple Table/form In The Clientside, How To Retrieve Data From Server Side

Need your help once again with MVC Core 2.0. So I am creating a page which an admin can add number of students into the system. Basically the page is something like this Number of

Solution 1:

You can create a view model with those 3 properties and use a collection of that view model as your HttpPost action method parameter. As long as the input element names(with 0 based index) matches with the property names, model binder will be able to map the posted data to your action method parameter.

Create a view model

publicclassStudentViewModel
{
    publicstring Name { set; get; }
    publicint Age { set; get; }
}

Use a collection of this view model in your http post action method

[HttpPost]
public IActionResult Save(IEnumerable<StudentViewModel> students)
{
    // to do : use students// to do : return something
}

For model binding to work, the input elements inside your form tag should have a name attribute value like below

<inputtype="text" name="[{n}].Name" />

Where {n} is the 0 based index of student rows

Now in the client side, render the dropdown and a container div element to which you can dynamically add the student rows based on the dropdown selection. Keep this container div inside a form tag

<selectid="studentCount"><optionvalue=""></option><optionvalue="1">1</option><optionvalue="2">2</option></select><formasp-action="Save"asp-controller="Students"method="post"><divid="students"></div><inputtype="submit" /></form>

Now in your client side script, listen to the change event on the dropdown, get the value and create n rows for students , where each row will have an input element for Name and Age. We will make sure that we are setting the name attribute value like [0].Name, [0].Age for the first row and [1].Name, [1].Age for the second row and so on.

$(function () {

    $('#studentCount').change(function (e) {
        var v = $(this).val();
        addRows(v);
    });
    functionaddRows(count) {
        var r = '';
        for (var i = 0; i < count; i++) {
            r += '<p>Name:<input type="text" name="[' + i + '].Name" />
                      Age:<input type="text" name="[' + i +'].Age" /></p>';
        }
        $("#students").html(r);
    }
});

The above code will create input elements with the correct name attribute value and when you submit the form , model binding will work fine.

Solution 2:

Some Background

What you want to do is not hard but you need to have a good understanding of web and MVC so you can make this to work. I will try and explain.

When the user requests the view, the request will arrive at your controller and your controller will return a view to the user like shown below:

public ActionResult Index()
{
    students.Add(new Student());
    return View(students);
}

// Hypothetical Student classpublicclassStudent
{
    publicstring Name { get; set; }
}

And here is the razor view:

@model Student
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2><form>
    @Html.TextBoxFor(model => model.Name)
    <inputtype="submit" /></form>

That razor view will be rendered by the MVC engine and HTML will be returned to the user. The part we are interested in is shown below:

<form>
    <input name="Name"type="text" value="">
    <inputtype="submit">
</form>

Please note the name of input above is Name. When the user fills out the form and submits it, it will post the value of the Name to the backend controller.

Your Problem

You are adding NOT one student like above, but many students. So here is what you need to do. When the request initially comes, you need to return a view that has a list of students but the list has only one student like shown below:

public ActionResult Index()
{
    var students = new List<Student>();
    students.Add(new Student());
    return View(students);
}

And here is the razor view:

@model List<Student>
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<form>
    @for (int i = 0; i < this.Model.Count(); i++)
    {
        @Html.TextBoxFor(model => this.Model[i].Name)
    }
    <input type="submit" />
</form>

Please note the for loop. If you use foreach, it will not work. Here is the HTML which will be rendered by the MVC engine:

<form>
    <input name="[0].Name"type="text" value="">
    <inputtype="submit">
</form>

Please note that now the name is [0].Name. In plain English, this input box is for the name of the student at index 0 (first student).

So in JavaScript code, you need to add more input boxes like above but you need to make sure they are named like [1].Name, [2].Name and so on. You need to do that for each and every property not just for Name.

Then when the user posts the form, you need an action which will serve a POST request for one or many students. Here is the what the controller action should look like:

[HttpPost]
public ActionResult Index(List<Student> students) { ... }

The DefaultModelBinder for MVC will figure out that the form which is posted has elements such as [x].Name within the form so it is smart enough to take each element and create Student objects from it and then add it to the a list and pass it to the above action.

Post a Comment for "Mvc Core Add Multiple Table/form In The Clientside, How To Retrieve Data From Server Side"