model binding of non-sequential arrays - asp.net-mvc

I am having a table in which i`m dynamically creating and deleting rows. How can I change the code such that the rows be added and deleted and the model info property filled accordingly.
Bearing in mind that the rows can be dynamically created and deleted, I may have Info[0], Inf0[3], info[4]... My objective is to be able to bind the array even if it`s not in sequence.
Model
public class Person
{
public int[] Size { get; set; }
public string[] Name { get; set; }
public Info[]info { get; set; }
}
public class Info
{
public string Address { get; set; }
public string Tel { get; set; }
View
<script type="text/javascript" language="javascript">
$(function () {
var count = 1;
$('#AddSize').live('click', function () {
$("#divSize").append('</br><input type="text" id="Size" name="Size" value=""/><input type = "button" id="AddSize" value="Add"/>');
});
$('#AddName').live('click', function () {
$("#divName").append('</br><input type="text" id="Name" name="Name" value=""/><input type = "button" id="AddName" value="Add"/>');
});
$('#AddRow').live('click', function () {
$('#details').append('<tr><td>Address</td><td> <input type="text" name="Info[' + count + '].Address"/></td><td>Tel</td><td><input type="text" name="Info[' + count++ + '].Tel"/></td> <td><input type="button" id="AddRow" value="Add"/> </td></tr>');
});
});
</script>
</head>
<body>
<form id="closeForm" action="<%=Url.Action("Create",new{Action="Create"}) %>" method="post" enctype="multipart/form-data">
<div id="divSize">
<input type="text" name="Size" value=""/> <input type="button" value="Add" id="AddSize" />
</div>
<div id="divName">
<input type="text" name="Name" value=""/> <input type="button" value="Add" id="AddName" />
</div>
<div id="Tab">
<table id="details">
<tr><td>Address</td><td> <input type="text" name="Info[0].Address"/></td><td>Tel</td><td><input type="text" name="Info[0].Tel"/></td> <td><input type="button" id="AddRow" value="Add"/> </td></tr>
</table>
</div>
<input type="submit" value="Submit" />
</form>
</body>
}
Controller
public ActionResult Create(Person person)
{
return new EmptyResult();
}

Here's a nice blog post that you might find helpful.

Related

How to create object that contains a list of object in a single form?

public class Basket
{
public int Id { get; set; }
public string Sharp { get; set; }
public string Material { get; set; }
public List<Fruit> Fruits { get; set; }
}
public class Fruit
{
public int Id { get; set; }
public string Color { get; set; }
public string Taste { get; set; }
}
With the above example, how could I create both Basket and Fruit in the same asp-form without using any JavaScript?
<form method="post" asp-controller="Basket" asp-action="Create">
<input asp-for="Material" />
<input asp-for="Sharp" />
#*I would like to also create custom amounts of new Fruit in this form.*#
<input type="submit" value="Submit" />
</form>
If my razor form is defined as the above example, how could I create custom amounts of Fruit and create Basket at the same form? It is possible to avoid using JavaScript in this case?
It is possible to avoid using JavaScript in this case?
Based on your scenario and current architecture what you need to do is, there should be a table where you would be adding your fruit object as it's a List<Fruit> Fruit kind of. As per your given code, your output should be as below:
So, I would say, Javascript would make it easier. If you would like to avoid javascript it wouldn't be impossible but would be costly and complex.
how could I create custom amounts of Fruit and create Basket at the
same form?
You could follow the below steps to achieve what you are trying to implement.
View:
#model DotNet6MVCWebApp.Models.Basket
<form method="post" asp-controller="Yonny" asp-action="Create">
<div class="form-group">
<label asp-for="Material" class="col-md-2 form-label"></label>
<input asp-for="Material" class="col-md-6 form-control" />
<span asp-validation-for="Material" class="form-span-error"></span>
</div>
<div class="form-group" style="padding-bottom:20px">
<label asp-for="Sharp" class="col-md-2 form-label"></label>
<input asp-for="Sharp" class="col-md-6 form-control" />
<span asp-validation-for="Sharp" class="form-span-error"></span>
</div>
#*I would like to also create custom amounts of new Fruit in this form.*#
<div style="padding-bottom:20px">
<button type="button" class="btn btn-primary" onclick="AddRow()">Add Fruit</button>
</div>
<div id="dataTable">
<table>
<thead>
<tr>
<th>Id</th>
<th>Color</th>
<th>Taste</th>
</tr>
</thead>
<tbody id="FruitList" data-count="0">
</tbody>
</table>
</div>
<input type="submit" class="btn btn-success" value="Submit" />
</form>
#section Scripts {
<script>
/*
. Hidding table on load
*/
document.getElementById('dataTable').style.display ='none';
function AddRow()
{
var countVal = parseInt($('#FruitList').attr('data-count'));
var html = '';
html += '<tr>';
html += '<td><input type="text" name="Fruits[' + countVal + '].Id" class="form-control"/></td>';
html += '<td><input type="text" name="Fruits[' + countVal + '].Color" class="form-control"/></td>';
html += '<td><input type="text" name="Fruits[' + countVal + '].Taste" class="form-control"/></td>';
html += '</tr>';
$('#FruitList').append(html);
countVal += 1;
$('#FruitList').attr('data-count', countVal);
/*
. Showing table when adding item into
*/
document.getElementById('dataTable').style.display ='block';
}
</script>
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("Id,Material,Sharp,Fruits")] DotNet6MVCWebApp.Models.Basket basket)
{
if (ModelState.IsValid)
{
//Save Basket
_context.Add(basket);
await _context.SaveChangesAsync();
//Add Fruits List
foreach (var item in basket.Fruits)
{
_context.Add(item);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Create));
}
return View(basket);
}
Note:
If you somehow got null data while sending request to controller make sure your binding property that is Bind("Id,Material,Sharp,Fruits") are same as name="Fruits[' + countVal + '].Id" inside the javascript function
Output:

Pass Object from view to controller using mvc4

View
#if (weekMaster != null)
{
using (Html.BeginForm("UpdatePlan", "generalPlan", FormMethod.Post, new { }))
{
<table class="table-bordered">
<tr>
#foreach (TermMaster obj in weekMaster.ToList())
{
<td align="center">
<span> #obj.termStartDate.ToString("dd MMM") - #obj.termEndDate.ToString("dd MMM")</span>
<br />
<input type="hidden" name="ObjHid" value="#obj" />
<input type="hidden" name="startDate" value="#obj.termStartDate" />
<input type="hidden" name="endDate" value="#obj.termEndDate" />
<input type="text" style="width:80%" name="weekSession" />
</td>
}
<td>
<input type="submit" value="Update" class="btn-primary" />
</td>
</tr>
</table>
} }
Controller
[HttpPost]
public ActionResult UpdatePlan(List<DateTime> startDate, List<DateTime> endDate, List<int> weekSession, List<TermMaster> ObjHid)
{
return View();
}
I am trying pass Class Object from View to Controller above TermMaster class Object pass using input method <input type="hidden" name="ObjHid" value="#obj" /> but showing NULL value if pass single value like startDate and endDate then it work fine.
What is wrong in my code? how to pass class object List in Post Method?
Please refer Image
You can not bind objects to controller from your input. You can serialize object to json. In the controller you can take your inputs value as string and deserialize it.
You have to do it by below approach.
Create a model instead of multiple parameters, and use index in cshtml.
public class model
{
public List<DateTime> startDate { get; set; }
public List<DateTime> endDate { get; set; }
public List<int> weekSession { get; set; }
public List<TermMaster> ObjHid { get; set; }
}
CSHTML
#{ int i = 0; }
#foreach (TermMaster obj in weekMaster.ToList())
{
<td align="center">
<span> #obj.termStartDate.ToString("dd MMM") - #obj.termEndDate.ToString("dd MMM")</span>
<br />
<input type="hidden" name="ObjHid[#i].termStartDate" value="#obj.termStartDate.ToString("dd MMM")" />
<input type="hidden" name="ObjHid[#i].termStartDate" value="#obj.termStartDate.ToString("dd MMM")" />
<input type="hidden" name="startDate[#i]" value="#obj.termStartDate" />
<input type="hidden" name="endDate[#i]" value="#obj.termEndDate" />
<input type="text" style="width:80%" name="weekSession[#i]" />
</td>
i++
}

Passing object from AngularJS to ASP.NET MVC Controller

I'm trying to pass some data to my MVC controller from AngularJS but the Customer object is always null on the MVC controller. What am I missing?
Angular
$scope.new = {};
$scope.AddCustomer = function () {
$http.post('/Customer/SaveCustomer', $scope.new).success(function () {
});
}
HTML
<input class="form-control" type="text" placeholder="CustomerID" ng-model="new.c.CustomerID" />
<input class="form-control" type="text" placeholder="CompanyName" ng-model="new.c.CompanyName" />
<button type="button" class="btn btn-primary" ng-click="AddCustomer()">Save</button>
C#
[HttpPost]
public void SaveCustomer(Customer customer)
{
....
}
public class Customer
{
public string CustomerID { get; set; }
public string CompanyName { get; set; }
}
Update your HTML like this :
Change new.c.CustomerID to new.CustomerID
<input class="form-control" type="text" placeholder="CustomerID" ng-model="new.CustomerID" />
<input class="form-control" type="text" placeholder="CompanyName" ng-model="new.CompanyName" />
Now this will work
$http.post('/Customer/SaveCustomer', $scope.new).success(function () {
});
First mind the camel case in javascript object
$scope.new = {
customerID: '',
companyName: ''
};
$scope.AddCustomer = function() {
$http.post('/Customer/SaveCustomer', $scope.new).success(function() {});
<!--check the changes in ng-model-->
<input class="form-control" type="text" placeholder="CustomerID" ng-model="new.customerID" />
<input class="form-control" type="text" placeholder="CompanyName" ng-model="new.companyName" />
<button type="button" class="btn btn-primary" ng-click="AddCustomer()">Save</button>
<!--Best of Luck-->
Your model seems to be
new = {
c : {
CustomerID : '',
CompanyName : ''
}
}
Which doesn't map to your Customer class. You should refer to new.CustomerID and new.CompanyName. Futhermore I would avoid using the new keyword as variable name.

can default model binder generate IEnumerable<FormItem>?

server:
public class FormItems
{
public IEnumerable<MyClass> Values { get; set; }
}
client:
<form id="myform" action="/" method="post">
<!-- Those inputs could be added dynamically -->
<input type="text" name="[0].Value" />
<input type="text" name="[1].Value" />
<input type="text" name="[2].Value" />
<input type="text" name="[3].Value" />
<button type="submit">OK</button>
</form>
and finally AJAXify the form:
$(function() {
$('#myform').submit(function() {
var form = $(this);
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(result) {
}
});
});
});
How can I use default model binder get the ajax data into strongly typed IEnumerable?
[HttpPost]
public JsonResult Save(FormItems data)
Assuming MyClass is something like this
public class MyClass
{
public string Value { get; set; }
}
Your html should look like this (note that name of each value input is prefixed by matching enumerable property name in FormItems)
< form id="myform" action="/" method="post">
<!-- Those inputs could be added dynamically -->
<input type="text" name="Values[0].Value" />
<input type="text" name="Values[1].Value" />
<input type="text" name="Values[2].Value" />
<input type="text" name="Values[3].Value" />
<button type="submit">OK</button>
</form>

how to Post list using ajax

My problem here is how to send the list values to the controller upon an ajax post. With my actual code, the list is null on post.
My view:
#using (Html.BeginForm("UsersList", "Project", FormMethod.Post, new { id = "Users" }))
{
<div id="MyList" >
<table>
<thead>
<tr><th></th><th>User</th><th>End date</th></tr>
</thead>
#Html.EditorFor(x => x.GetUsers)
</table>
</div>
<script type="text/javascript">
$(function () {
$('#MyList).dialog({
autoOpen: false,
width: 820,
buttons: {
"Save": function () {
$("#Users").submit();
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
</script>
Model:
public class ProjectModel
{
public List<ProjectList>GetUsers{get;set;}
}
public class ProjectList
{
public bool Selected { get; set; }
public int UserID { get; set; }
}
My controller:
[HttpPost]
public ActionResult UsersList(ProjectModel model)
{
return View(model);
}
Sending a list can be difficult. I think MVC 3.0 has (in-built) support for sending JSON to the controller which would make this easier.
However with prior versions I think this article should be what your looking for:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Effectively you give everything in the list the same name in your HTML (as the name will be what gets sent in the key/value string that gets sent and it will bind as a list.
For more complex items you name each object property but add an index to show which object they get attached too:
<form method="post" action="/Home/Create">
<input type="text" name="[0].Title" value="Curious George" />
<input type="text" name="[0].Author" value="H.A. Rey" />
<input type="text" name="[0].DatePublished" value="2/23/1973" />
<input type="text" name="[1].Title" value="Code Complete" />
<input type="text" name="[1].Author" value="Steve McConnell" />
<input type="text" name="[1].DatePublished" value="6/9/2004" />
<input type="text" name="[2].Title" value="The Two Towers" />
<input type="text" name="[2].Author" value="JRR Tolkien" />
<input type="text" name="[2].DatePublished" value="6/1/2005" />
<input type="submit" />

Resources