Search code examples
c#asp.net-corerazor-pages

c# RazorPage - NullReferenceException when attempting to add record via modal popup


I'm relatively new to c# razorpages. I've created an example project using entityframework and have generated my pages using ScaffoldedItems functionality.

Rather than having a create page, I want a modal popup to create records from the index page but I'm struggling to get them to work.

I've got my modal popup opening with a textbox but when clicking submit, i'm immediately getting a NullReferenceException from the loop which displays the table.

enter image description here

Please assist.

    @page
@model ResellingWEB.Pages.Brands.IndexModel

@{
    ViewData["Title"] = "Brands";
}

<h1>Brands</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
                <form method="post" asp-page="./Index" asp-handler="Create">


                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                    <div class="form-group">
                        <label class="control-label">Brand Name</label>
                        <input class="form-control" required="required" name="BrandName" />
                    </div>
                    <div class="form-group">
                        <input type="submit" value="Create" class="btn btn-primary" />
                    </div>
                </form>
      </div>

    </div>
  </div>
</div>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Brand[0].BrandName)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model.Brand) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.BrandName)
            </td>
            <td>
                <a asp-page="./Edit" asp-route-id="@item.BrandID">Edit</a> |
                <a asp-page="./Details" asp-route-id="@item.BrandID">Details</a> |
                <a asp-page="./Delete" asp-route-id="@item.BrandID">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using ResellingWEB.Data;
using ResellingWEB.Models;

namespace ResellingWEB.Pages.Brands
{
    public class IndexModel : PageModel
    {
        private readonly ResellingWEBContext _context;

        public ResellingWEBContext Context => _context;

        public IndexModel(ResellingWEBContext context)
        {
            _context = context;
        }

        public IList<Brand> Brand { get;set; } = default!;

        public async Task OnGetAsync()
        {
            Brand = await _context.Brands.ToListAsync();
        }

        public async Task<IActionResult> OnPostCreateAsync(string BrandName)
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            var brand = new Brand { BrandName = BrandName };

            _context.Brands.Add(brand);
            await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        }


    }
}

Solution

  • To sum up at the beginning, the exception is due to not triggering the OnPostCreateAsync method, we need to use asp-page-handler="Create" instead.

    Process here:

    I reproduced your issue in my side, that's because after clicking the submit button, it sends a post request to /Brands but not the one you defined by asp-handler="Create".

    enter image description here

    If we just need to handle this null exception, we just need to add a OnPost() method.