I have an asp.net mvc application. I want to perform and update operation.I want to show you my code before explain my problem sorry I am not fluent in english thats why I prefer to show my code first.Here I have an index page that shows all items in database with a table
@model IEnumerable<InOut.Models.Item>
@if (Model.Count() > 0)
{
<table style="width: 100%; text-align: center">
<thead>
<tr>
<th>Item Name</th>
<th>Borrower</th>
<th>Lender</th>
<th >Edit</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td style="width: 25%">@item.borrower</td>
<td style="width: 25%">@item.Lender</td>
<td style="width: 25%">@item.ItemName</td>
<td style="width: 13%">
<a asp-controller="Item" asp-action="Delete" asp-route-id="@item.id" onclick="showAlert()" id="btn1" style="text-decoration: none; color: white">delete</a>
<a asp-controller="Item" asp-action="Update" asp-route-id="@item.id" id="btn1" style="text-decoration: none; color: white">Update</a>
</td>
</tr>
}
</tbody>
</table>
}
else
{
<p> No Items created </p>
}
Here is the index action for that view
public IActionResult Index()
{
IEnumerable<Item> items = _dbContext.Items;
return View(items);
}
In the foreach loop I have a button to update the object on that row it has an action named "Update" in controller class.here is the code to get the item on that row.
//Get Item
public IActionResult Update(int? id)
{
var item = _dbContext.Items.Single(o => o.id == id);
return View(item);
}
this action sends the selected item properties to the update view.here is the code of view
<form method="post" asp-action="Create">
<input asp-for="id" hidden/>
<div >
<label >Item Name </label>
<input type="text" aria-describedby="emailHelp" asp-for="ItemName">
</div>
<div >
<label >Borrower</label>
<input type="text" asp-for="borrower">
</div>
<div >
<label >Lender</label>
<input type="text" asp-for="Lender">
</div>
<button asp-controller="Item" asp-action="Update" type="submit" style="margin-top: 10px">Submit</button>
submit button sends properties to the overloaded action update with the parameter of item. after update operation I want it to show me the index page. here is the overloaded update action
// Update Item
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Update(Item item)
{
_dbContext.Update(item);
_dbContext.SaveChanges();
return View("Index");
}
Problem starts here. When I run application after submitting changes I want it to show me the index action update operation working well.but when it try to show me the index page it gives me this error.
ArgumentNullException: Value cannot be null. (Parameter 'source') and it refers to the if statement in the index page it
now if I use redirectToAction return instead of View like this...
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Update(Item item)
{
_dbContext.Update(item);
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
It works as I wanted. I want to know what is the problem with the first approach and is there any difference between those 2 return types?
CodePudding user response:
the difference is here
public IActionResult Index()
{
IEnumerable<Item> items = _dbContext.Items; //maybe you need to add .ToList(); ??
return View(items);
}
when you are using an index action you create the list of items as a model and pass them to the view. But you don't create any model when you call Index view from an update action. If you still want to return view from an update you can do it this way
_dbContext.Update(item);
_dbContext.SaveChanges();
var items = _dbContext.Items.ToList();
return View("Index", items);
or if update and index actions are in the same controller I usually just call an action as a method
_dbContext.Update(item);
_dbContext.SaveChanges();
return Index();
CodePudding user response:
When you use:
return View("Index");
it doesn't execute the Index
action. That means this line:
IEnumerable<Item> items = _dbContext.Items;
is never executed. So when execution passes to the view, and it reaches this condition:
@if (Model.Count() > 0)
Model
is null
, so trying to invoke the Count
method results in the exception being thrown. This is one reason why you use
return RedirectToAction("Index");
The second reason to do this is to follow what's called Post/Redirect/Get. This is a pattern that helps to prevent duplicate form submissions.