Home > Mobile >  ASP.NET MVC ArgumentNullException: Value cannot be null. (Parameter 'source')
ASP.NET MVC ArgumentNullException: Value cannot be null. (Parameter 'source')

Time:02-16

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.

  • Related