Search code examples
asp.net-coremodel-view-controllerrazordropdownargumentnullexception

Navigate to new view on button click in ASP.NET Core 3.1 MVC


I am trying to navigate the user to a new page with a button click. I am having issues with rendering the new view. Any time I do click on the button, I either get an error for a dropdown on my page, or I get the home page view but with my desired route in the URL. I wanted to note that the user will be navigating to this page from the home page, which I made into my new landing page on the app. I wanted to point that out in case something I did here can be modified. How I created a new landing page

I want to navigate from my landing page to my book inventory page.

My View (On the landing page):

<form method="post" asp-controller="Home" asp-action="Home" role="post">
    <div class="form-group">
        <label asp-for="bookName"></label>
        <select name="bookName" asp-items="@(new SelectList(ViewBag.message, "ID", "bookName"))">
</select>
    </div>
    <div class="form-group">
        <input type="submit" value="Submit" class="btn btn-primary" />
    </div>
</form>
<div class="row">
    <div class="form-group">
        <a asp-controller="BookInventory" asp-action="Index">
            <input type="button" value="Book Inventory Page" /> 
        </a>
    </div>
</div>

My Controller (On my landing page)

        public void GetBooksDDL()
        {
            List<BookModel> bookName = new List<BookModel>();
            bookName = (from b in _context.BookModel select b).ToList();
            bookName.Insert(0, new BookModel { ID = 0, bookName = "" });
            ViewBag.message = bookName;
        }

        [HttpGet("[action]")]
        [Route("/Home")]
        public IActionResult Home()
        {
            GetBooksDDL()
            return View();
        }

My Controller (On my book inventory page):

        [HttpGet("[action]")]
        [Route("/Index")]
        public IActionResult Index()
        {
            return View();
        }

I wanted to note that my breakpoint on my book inventory controller does hit the 'return View()', but it will still render the items from the homepage.

The error I get with the book dropdown says:

ArgumentNullException: Value cannot be null. (Parameter 'items') Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.ctor(IEnumerable items, string dataValueField, string dataTextField, IEnumerable selectedValues, string dataGroupField).

I'm wondering why I'm getting this error when I'm trying to navigate to a different page. Since this is the new landing page, is it possible that it is passing along all of its data to the rest of the pages?


Solution

  • ArgumentNullException: Value cannot be null. (Parameter 'items') Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.ctor(IEnumerable items, string dataValueField, string dataTextField, IEnumerable selectedValues, string dataGroupField).

    About this error, it means that you didn't set the value for the select element, before return to the view, please check the ViewBag.message value, make sure it contains value.

    Note: Please remember to check the post method, if the Http Get and Post method returns the same page, make sure you set the ViewBag.message value in both of the action methods.

    I wanted to note that my breakpoint on my book inventory controller does hit the 'return View()', but it will still render the items from the homepage.

    In the BookInventory Controller Index action method, right click and click the "Go to View" option, make sure you have added the Index view.

    enter image description here

    Based on your code, I have created a sample using the following code, it seems that everything works well.

    Code in the Home Controller:

        [HttpGet("[action]")]
        [Route("/Home")]
        public IActionResult Home()
        {
            GetBooksDDL();
            return View();
        }
    
        [HttpPost("[action]")]
        [Route("/Home")]
        public IActionResult Home(BookModel book, string bookName)
        {
            GetBooksDDL();
            //used to set the default selected value, based on the book id (bookName) to find the book.
            List<BookModel> booklist = (List<BookModel>)ViewBag.message;
            book = booklist.Find(c => c.ID == Convert.ToInt32(bookName));
    
            return View(book);
        }
    

    Code in the Home view:

    @model BookModel
    @{
        ViewData["Title"] = "Home";
    }
    
    <h1>Home</h1>
    
    <form method="post" asp-controller="Home" asp-action="Home" role="post">
        <div class="form-group">
            <label asp-for="bookName"></label>
                 <select name="bookName" asp-items="@(new SelectList(ViewBag.message, "ID", "bookName", Model == null? 0:Model.ID))">
            </select>
        </div>
        <div class="form-group">
            <input type="submit" value="Submit" class="btn btn-primary" />
        </div>
    </form>
    <div class="row">
        <div class="form-group">
            <a asp-controller="BookInventory" asp-action="Index">
                <input type="button" value="Book Inventory Page" />
            </a>
        </div>
    </div>
    

    Code in the BookInventory controller:

    public class BookInventoryController : Controller
    {
        [HttpGet("[action]")]
        [Route("/Index")]
        // GET: BookInventory
        public ActionResult Index()
        {
            return View();
        }
    

    The screenshot as below:

    enter image description here

    If still not working, please check your routing configuration, perhaps there have some issue in the routing configure.