Select rows and pass data(ID) to next view, MVC5 C# - c#

I have been trying to select multiple rows from my table of data(Generated using EF) and then pass all selected rows to the next view to perform some action. On passing the data to the next view i am getting the following error :
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Temporary local of type 'int[]'> was null.
Any help on how to solve this will be appreciated.
Below is my code:
View:
<div class="row">
<div class="col-md-12">
<!-- Advanced Tables -->
<div class="panel panel-default">
<div class="panel-heading">
#using (Html.BeginForm()) {
<form action="#" method="post">
<label>Search by Company Name:</label> #Html.TextBox("SearchString")
<input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;">
<label>Search by Card Number:</label> #Html.TextBox("searchCard")
<input type="submit" value="Go" placeholder="Search" style="background-color: #0a9dbd; color: white; border-color: #0a9dbd;">
Export to Excel
</form>
}
</div>
<div class="panel-body">
Add Gift Card
Get Card Balance
Load Cards
<br />
<br />
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th>Card ID</th>
<th>Company</th>
<th>Card Number</th>
<th>Card Number 2</th>
<th>Date Created</th>
<th>Card Status</th>
<th>Discount Level ID</th>
<th>Loyalty Level ID</th>
<th>Gift Card Enabled</th>
<th>Loyalty Enabled</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td><input type="checkbox" name="ids" value="#item.CardID" /></td>
<td>#item.CardID</td>
<td>#item.Customer.CustomerCompanyName</td>
<td>#item.CardNumber</td>
<td>#item.CardNumber2</td>
<td>#item.CardDate</td>
<td>#item.CardStatus</td>
<td>#item.DiscountLevelID</td>
<td>#item.LoyaltyLevelID</td>
<td>#item.GiftCardEnabled</td>
<td>#item.LoyaltyEnabled</td>
<td>
<i class="fa fa-edit "></i> Edit <br />
</td>
</tr>
}
</tbody>
</table>
Page #(Model.PageCount
< Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount #Html.PagedListPager(Model, page=> Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
</div>
</div>
</div>
<!--End Advanced Tables -->
</div>
</div>
Controller:
public ActionResult PostCards(int[]ids)
{
var myObject = new Card();
foreach(var id in ids)
{
myObject = db.Cards.Single(o => o.CardID == id);
return RedirectToAction("LoadCards", myObject);
}
return View();
}
public ActionResult LoadCards()
{
return View();
}
I need the selected data to be passed to the LoadCards view.

Let us first look at the NullReference you are getting. The problem here is that no correct index is created to bind the checkboxes to an array. Use a for loop instead of foreach. In MVC/Razor, how do I get the values of multiple checkboxes and pass them all to the controller?
To get the desired behaviour:
change the foreach to a for loop so the correct indices for sending the data will be created.
add a checkbox in each row that lets the user select the rows to submit.
your action should recieve a collection of models for each row. This model always transports the CardId and tells us whether it was selected.
public class SelectedCardModel {
public int CardId { get; set; }
public bool IsSelected {get; set;}
}
In the view:
#using (Html.BeginForm("PostCards", "CustomerView", FormMethod.Post) {
// <table> etc ...
<tbody>
#for (var i = 0; i < Model.Count; i++) {
#{ var item = Model.ElementAt(i); }
<tr>
<td>
#Html.Hidden("CardId[" + i + "]")
#Html.CheckBox("IsSelected[" + i + "]")
</td>
// display other properties of item ...
<td>#item.CardID</td>
// ...
</tr>
}
</tbody>
</table>
<button type="submit">Load Cards</button>
}
Action:
[HttpPost]
public ActionResult PostCards(SelectedCardModel[] selectedCards) {
foreach(var card in selectedCards) {
if (card.IsSelected) {
var selectedId = card.CardId;
// ...
}
}
}

Related

Return ViewData from view to controller razor pages

I have view is C#:
#{
var itemList = (List<Item>)ViewData["itemsList"];
}
<div class="row" style="margin-top: 10px;">
<div class="col-md-6">
#if (itemList != null)
{
var id = 0;
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th></th>
<th>Id</th>
<th>Type</th>
</tr>
</thead>
<tbody>
#foreach (var result in itemsList)
{
<tr>
<td>#(++id)</td>
<td><input type="checkbox" value="true" #(result.Checked ? "checked" : "")></td>
<td>#result.Id</td>
<td>#result.Type</td>
</tr>
}
</tbody>
</table>
}
<div class="row justify-content-end" style="margin-top: 20px;">
<div class="col-md-2">
<form asp-controller="Control" asp-action="Remove" method="post">
<input type="hidden" name="tableName" value="table"/>
<input type="hidden" name="items" value="#itemList"/>
<div style="margin-left: -10px;" class="col-md-2">
<button class="btn btn-danger" title="Remove" type="submit">Remove</button>
</div>
</form>
</div>
</div>
</div>
</div>
I want to remove items from table, where user checks the checkbox. My idea was to update each checked item withing the list (result.Checked property) and then send array to Remove method:
[HttpPost]
public async Task<IActionResult> Remove(string tableName, List<ChangeQueueItem> items)
{
try
{
var toDelete = items.Where(x => x.Checked == true);
await _repository.RemoveFromQueue(toDelete, tableName);
}
catch (Exception e)
{
TempData["error"] = e.Message;
}
return RedirectToAction("Index");
}
I am trying to send that list like this:
<input type="hidden" name="items" value="#itemList"/>
however the value is null. How should I do it?
Update: data is loaded here:
[HttpGet]
public async Task<IActionResult> Index()
{
var items = await _repository.GetAll();
ViewData["itemsList"] = items;
ViewData["error"] = TempData["error"];
return View("Index");
}
First, you set value using ViewData["itemsList"] = items;, but get it by var itemList = (List<Item>)ViewData["itemList"];.
Change key value to be consistent: for example, replace itemList by itemsList in the view.
Second, to pass list from the view to the controller action method apply indexes to the items (only the <tbody> content is shown):
<tbody>
#using (Html.BeginForm("Remove", "Control"))
{
#Html.Hidden("tableName", "table")
#for (int i = 0; i < itemsList.Count; i++)
{
#Html.Hidden("items[" + i + "].Id", itemsList[i].Id)
#Html.Hidden("items[" + i + "].Type", itemsList[i].Type)
<tr>
<td>#(++id)</td>
<td>#Html.CheckBox("items[" + i + "].Checked", itemsList[i].Checked)</td>
<td>#itemsList[i].Id</td>
<td>#itemsList[i].Type</td>
</tr>
}
<tr><td><button class="btn btn-danger" title="Remove" type="submit">Remove</button></td></tr>
}
</tbody>
Or the same without the helper (only the <tbody> content is shown):
<tbody>
<form asp-controller="Control" asp-action="Remove" method="post">
<input type="hidden" name="tableName" value="table" />
#for (int i = 0; i < itemsList.Count; i++)
{
<input type="hidden" name="#("items[" + i + "].Id")" value="#itemsList[i].Id" />
<input type="hidden" name="#("items[" + i + "].Type")" value="#itemsList[i].Type" />
<tr>
<td>#(++id)</td>
<td><input name="#("items[" + i + "].Checked")" type="checkbox" value="true" #(itemsList[i].Checked ? "checked" : " ") /></td>
<td>#itemsList[i].Id</td>
<td>#itemsList[i].Type</td>
</tr>
}
<tr><td><button class="btn btn-danger" title="Remove" type="submit">Remove</button></td></tr>
</form>
</tbody>
It doesn't appear that you're setting the TempData["itemList"]; I can't see it in the code.
You should be setting it using something like:
TempData["itemList"] = toDelete;

Implement delete button on each table row using model binding and POST request

On my view, I have a table with a form that I want to use to delete a particular row. I use a foreach loop to generate an hidden input field with the row value that I want to pass to the controller and asp-for tag for model biding, and a submit button.
The value that is passed to the controller is always the first row. I'm inclined to think that the reason for this behavior is that the generated input fields all have the same name attribute, because the asp-for expression is invariant for every iteration of the foreach loop.
Is there a straight-forward way to implement this using a form and a POST request, or should I just use anchors with route values, i.e., GET requests?
Here's my ViewModel:
public class RolesViewModel
}
public IList<AppUser> UsersInRole {get; set;}
public string SelectedRole {get; set;}
public RemoveUserFromRole RemoveUser {get; set;}
public class RemoveUserFromRole
{
public string UserName {get; set;}
public string RoleName {get; set;}
}
}
My View
<form method="post" asp-action="RemoveUser" id="removeUserForm"></form>
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
#foreach (var user in Model.UsersInRole)
{
<tr>
<td>#user.UserName</td>
<td class="text-center">
<input form="removeUserForm" asp-for="RemoveUser.UserName" type="hidden" value="#user.UserName" />
<input form="removeUserForm" asp-for="RemoveUser.RoleName" type="hidden" value="#Model.SelectedRoleName" />
<button form="removeUserForm" type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
And my action method in controller
[HttpPost]
public async Task<IActionResult> RemoveUser(RolesViewModel model)
{
//model.RemoveUser.UserName always have the value from the first row
var user = await _userManager.FindByNameAsync(model.RemoveUser.UserName);
if (user == null)
return RolesError(await GetModel());
var result = await _userManager.RemoveFromRoleAsync(user, model.RemoveUser.RoleName);
if (!result.Succeeded)
return RolesError(await GetModel());
return RedirectToAction("Roles", new { roleName = model.RemoveUser.RoleName });
}
Thanks in advance for your time.
According to your codes, I found you have multiple hidden filed which contains the user.UserName.
If you click the submit button, it will upload all the hidden filed value to the code-behind and it will just bind the first one, this is the reason why your model is always first one.
You could find the formdata in F12 developtool's network.
To solve this issue, we have a easily but not a good solution.
We could set mutiple form tag in your table to avoid post all the all the hidden filed username value to controller:
Like below:
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
#foreach (var user in Model.UsersInRole)
{ int i = 0;
<tr>
<td>#user.UserName</td>
<td class="text-center">
<form method="post" asp-action="RemoveUser" id="#user.UserName">
<input form="#user.UserName" name="RemoveUser.UserName" type="hidden" value="#user.UserName" />
<input form="#user.UserName" name="RemoveUser.RoleName" type="hidden" value="#Model.SelectedRole" />
<button form="#user.UserName" type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times">iiiii</i>
</button>
</form>
</td>
</tr>
}
</tbody>
</table>
If you choose this way, you should rebuild all your view's html makeup.
Besides, you could try to use ajax to achieve your requirement, this solution is better than before solution. You could use jquery to get the right form data according to the submit button's id or position and then use jquery ajax to post the form data into controller. Then you could return the redirect url instead of RedirectToAction methods.
More details about how to use ajax to send form data, you could refer to below codes:
#model MVCRelatedIssue.Models.RolesViewModel
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<form method="post" asp-action="RemoveUser" id="removeUserForm">
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
#foreach (var user in Model.UsersInRole)
{
<tr>
<td>#user.UserName</td>
<td class="text-center">
<input form="removeUserForm" name="RemoveUser.UserName" type="hidden" value="#user.UserName" />
<input form="removeUserForm" name="RemoveUser.RoleName" type="hidden" value="#Model.SelectedRole" />
<button form="removeUserForm" type="submit" id="submit" class="btn btn-sm btn-link text-danger py-0 my-0 subbtn">
<i class="fas fa-times">iiiii</i>
</button>
</td>
</tr>
}
</tbody>
</table>
</form>
#section Scripts{
<script>
$(document).ready(function () {
$(".subbtn").bind("click", function (e) {
e.preventDefault();
var formdata = new FormData();
var UserName = $(this).prev().prev().val();
formdata.append("RemoveUser.UserName", UserName);
console.log(UserName);
var roleName = $(this).prev().val();
formdata.append("RemoveUser.RoleName", roleName);
console.log(roleName);
$.ajax({
type: "POST",
url: "/RemoveUser/RemoveUser",
data: formdata,
contentType: false,
processData: false,
success: function (data) {
alert("success");
window.location.href = data;
}
});
});
});
</script>
}
Controller:
[HttpPost]
public async Task<IActionResult> RemoveUser(RolesViewModel model)
{
//model.RemoveUser.UserName always have the value from the first row
//var user = await _userManager.FindByNameAsync(model.RemoveUser.UserName);
//if (user == null)
// return RolesError(await GetModel());
//var result = await _userManager.RemoveFromRoleAsync(user, model.RemoveUser.RoleName);
//if (!result.Succeeded)
// return RolesError(await GetModel());
string redirecturl = "/RemoveUser/Roles?roleName=" + model.RemoveUser.RoleName;
return Ok(redirecturl);
}
Result:
You can use a Delete Link
in View
#foreach (var user in Model.UsersInRole)
{
<a href="#Url.Action("RemoveUser", "YOUR_Controller",new {username = user.UserName})"
onclick="return confirm('Do You want to Delete');"
</a>
}
In Controller
[HttpGet]
public async Task<IActionResult> RemoveUser(String username)
{
// Get the user Object the delete it
}
I was capable of solving this issue with minimal code footprint.
As it turns out, <td> tags can have forms, so, knowing that, it is possible to have a different form on each row, like so:
View:
//Remove inline table form
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
#foreach (var user in Model.UsersInRole)
{
<tr>
<td>#user.UserName</td>
<td class="text-center">
//now each form will have the correct, row-wise formdata
<form method="post" asp-action="RemoveUser">
<input asp-for="RemoveUser.UserName" type="hidden" value="#user.UserName" />
<input asp-for="RemoveUser.RoleName" type="hidden" value="#Model.SelectedRoleName" />
<button type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times"></i>
</button>
</form>
</td>
</tr>
}
</tbody>
</table>

could not update in session data in asp.net core 2.2

I want to update session data (List type)using a controller. but it's not working.it gives me an error.
Here is my code:
[HttpGet]
public IActionResult Cart()
{
List<Spray> spray = HttpContext.Session.Get<List<Spray>>("spray");
if (spray == null)
{
spray = new List<Spray>();
}
return View(spray);
}
[HttpPost]
public IActionResult Cart(int id)
{
List<Spray> spray = HttpContext.Session.Get<List<Spray>>("spray");
for (int i = 0; i < 10; i++)
{
if (spray[i].Id.Equals(id))
{
spray[i].Quantity++;
}
}
return RedirectToAction(nameof(Cart));
}
View
#using HuddsonBay.Models
#model List<Spray>
#{
ViewData["Title"] = "Cart";
}
<h1>Your Cart</h1>
<br />
<div class="row">
<table class="table table-bordered">
<thead>
<tr>
<th>Image</th>
<th>Name</th>
<th>Price</th>
<th>Product Type</th>
<th>Color</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<img src="~/#item.Image" width="200px" height="150px" />
</td>
<td>#item.Name</td>
<td>#item.Price</td>
<td>#item.Quantity</td>
<td>
<partial name="_QuantityPartial" model="#item.Id" />
</td>
<td>#item.ProductColor</td>
<td>
<a asp-area="Customer" asp-action="Remove" asp-controller="SprayShow" asp-route-id="#item.Id" class="btn btn-danger">
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<div class="col-6">
<a asp-action="Index" asp-controller="SprayShow" class="btn btn-primary">Back To Home</a>
</div>
<div class="col-6 text-right">
<h3>Total Amount</h3>
<h3>Grand Total : #Model.Sum(c => c.Price)</h3>
<a asp-area="Customer" asp-action="Checkout" asp-controller="Order" class="btn btn-info">Process To CheckOut</a>
</div>
</div>
_QuantityPartial.cshtml
#model int
<form method="post">
<td style="width:150px">
<div class="btn-group">
#*<a asp-action="Index" class="btn btn-danger" asp-route-id="#Model">Add</a>*#
<input type="submit" asp-action="Cart" asp-route-id="#Model" value="+" />
</div>
</td>
</form>
and here is my output:
and when I click "+" button, I found an error:
will be increment or decrement using a controller. How I will solve this.
I am beginner, please help anyone.
The List<Spray> spray in your post method is a new Instance of the list in your session, after change the propertity's value, you need to store the new list again in session. Otherwise it is still the orignally one.
A test example based on your codes:
View:
#model List<Spray>
#{
ViewData["Title"] = "Cart";
}
<h1>Your Cart</h1>
<br />
<div class="row">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
<th></th>
<th>Color</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Name</td>
<td>#item.Price</td>
<td>#item.Quantity</td>
<td>
<partial name="_QuantityPartial" model="#item.Id" />
</td>
<td>#item.ProductColor</td>
<td>
<a asp-area="Customer" asp-action="Remove" asp-controller="SprayShow" asp-route-id="#item.Id" class="btn btn-danger">
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<div class="col-6">
<a asp-action="Index" asp-controller="SprayShow" class="btn btn-primary">Back To Home</a>
</div>
<div class="col-6 text-right">
<h3>Total Amount</h3>
<h3>Grand Total : #Model.Sum(c => c.Price)</h3>
<a asp-area="Customer" asp-action="Checkout" asp-controller="Order" class="btn btn-info">Process To CheckOut</a>
</div>
</div>
Controller:
[HttpGet]
public IActionResult Cart()
{
var value = HttpContext.Session.GetString("spray");
var spray = JsonConvert.DeserializeObject<List<Spray>>(value);
if (spray == null)
{
spray = new List<Spray>();
}
return View(spray);
}
[HttpPost]
public IActionResult Cart(int id)
{
var value = HttpContext.Session.GetString("spray");
var spray = JsonConvert.DeserializeObject<List<Spray>>(value);
for (int i = 0; i < spray.Count; i++)
{
if (spray[i].Id.Equals(id))
{
spray[i].Quantity++;
}
}
HttpContext.Session.SetString("spray", JsonConvert.SerializeObject(spray));
return RedirectToAction(nameof(Cart));
}
Result:
Your problem maybe not be your Session. Is about the number of the items from the List<Spray> spray. The exception is about the length of the spray list. Your for goes always up to 10 and is possible that you have less items in your list and that is why you have that Out of Range exception.
You have hardcoded 10 in your for loop. If u have less than 10 items in your list it will overflow.
Change to this (or use a foreach)
[HttpPost]
public IActionResult Cart(int id)
{
List<Spray> spray = HttpContext.Session.Get<List<Spray>>("spray");
for (int i = 0; i < spray.Count; i++)
{
if (spray[i].Id.Equals(id))
{
spray[i].Quantity++;
}
}
return RedirectToAction(nameof(Cart));
}
Another option is to skip the loop and do like this instead
public IActionResult Cart(int id)
{
List<Spray> spray = HttpContext.Session.Get<List<Spray>>("spray");
var item = spray.SingleOrDefault(x => x.Id.Equals(id));
if(item != null)
{
item.Quantity++;
}
return RedirectToAction(nameof(Cart));
}

How to pass multiple checkbox parameters from foreach

I have a form in my View with a table and on each cell i have a checkbox. I already have individual Ids for every single checkbox but I dont know how to pass them individually to controller action. I know how to pass single parameters over the "name" attribute but Im not sure on how to handle it with so many diffrent checkboxes.
View
#{
bool IsOwnRegistration = false;
foreach (var item in Model.Events.Where(i => i.UserId == Model.UserID && Convert.ToDateTime(i.Date) > dateTime))
{
if (item.HasCreatedOtherUsers == null)
{
IsOwnRegistration = true;
}
string Surname = "";
string Lastname = "";
<tr>
#{
foreach (var Useritem in Model.Users.Where(i => i.UserId == item.HasCreatedOtherUsers))
{
Surname = Useritem.Vorname;
Lastname = Useritem.Nachname;
}
if (IsOwnRegistration == true)
{
<th style="background-color:grey; width:33%;">
Meine Reservation
</th>
<th style="width:33%;">#item.Date</th>
<th style="width:33%;">
<div class="custom-control custom-checkbox ">
<input type="checkbox" class="custom-control-input" name="#item.EventId" id="#item.Date#item.EventId">
<label class="custom-control-label" for="#item.Date#item.EventId"><i style="color:red;" class="fas fa-trash-alt"></i>
</label>
</div>
</th>
}
else
{
<th style="width:33%;">#Surname #Lastname</th>
<th style="width:33%;">#item.Date</th>
<th style="width:33%;">
<div class="custom-control custom-checkbox ">
<input type="checkbox" class="custom-control-input" name="#item.EventId" id="#item.Date#item.EventId">
<label class="custom-control-label" for="#item.Date#item.EventId"><i style="color:red;" class="fas fa-trash-alt"></i>
</label>
</div>
</th>
}
}
Controller
public ActionResult DeleteRegistrations(Need to get values of all checkboxes)
{
return RedirectToAction("HomePage");
}
In order to transmit the selected checkboxes to the action method, the checkboxes should share a common name that matches the parameter name of the action method. The following sample shows a Razor view that lists some strings in a table, creating a checkbox for each string:
#model IEnumerable<string>
#{
ViewBag.Title = "Home Page";
}
<div class="row">
<div class="col-md-12">
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<table>
#foreach (var s in Model)
{
<tr>
<td>
<input type="checkbox" name="selectedValues" value="#s" id="#s" />
<label for="#s">#s</label>
</td>
</tr>
}
</table>
<input type="submit" />
}
</div>
</div>
Please note that the name attribute of the checkboxes is set to "selectedValues", the value attribute is set to the original string (or an id in a more complex scenario).
The form is submitted by a POST request to the following action method:
[HttpPost]
public ActionResult Index(IEnumerable<string> selectedValues)
{
return View(selectedValues);
}
In the POST request, all the values of all checked checkboxes are transmitted as key value pairs in the form "name=value". As all of the checkboxes share the same name, ASP.NET MVC can deserialize this into an IEnumerable<string>.

Asp.net Core MVC - on form posting to controller IEnumerable model in controller action is empty

I have a problem when I am trying to post IEnumerable from razor view to Controllor action method. Also result is the same if I use List.
I post my controllor action method also in comment. In my controllor action method I got list that is empty.
This is my View:
#model IEnumerable<Subject>
<form asp-action="AddNewSubjects" asp-controller="Teacher" method="post" role="form" class="form-horizontal">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Number of class</th>
<th>Level</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
var item = Model.ToList();
#for(int i=0;i<Model.Count();i++)
{
<tr>
<td>#item[i].ID</td>
<td>#item[i].Name</td>
<td>#item[i].ClassNumber</td>
<td>#item[i].Level</td>
</tr>
}
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-5">
<input type="submit" class="btn btn-primary" value="Save all subjects" />
</div>
</div>
</form>
This is my Controller:
private readonly ISubjectService _subjectService;
public TeacherController(ISubjectService subjectService)
{
_subjectService= subjectService;
}
[HttpPost]
public IActionResult AddNewSubjects(IEnumerable<Subject> subjects)
{
var newSubjects= (from p in subjects
where p.State== Status.New
select p);
var result = _subjectService.SaveTeacherSubjects(newSubjects);
return View("ProfesorPages");
}
I have no idea what you're trying to do here. Your form doesn't have any input element except the submit button. Of course you're not seeing anything posted back.
#model IEnumerable<Subject>
<form>
...
<tbody>
#for(int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
<input type="hidden" asp-for="Model[i].ID" />
</td>
<td>
<input type="text" asp-for="Model[i].Name" />
</td>
...
</tr>
}
</tbody>
...
</form>
Why??
Why did you convert your IEnumerable to a list named item? Why not just enumerate your subjects directly?
Why not create a different set of models called ViewModel and pass that to the View, instead of using your model from your database directly on the View?

Categories

Resources