Trying to add new data to table leads to an error: The parameters dictionary contains a null entry for parameter ‘id’ of non-nullable type

I am taking an ASP.NET course an Udemy. Unfortunately, it’s an old course, and I don’t believe to get an answer there.

Now, what exactly is going on.
At this stage of the course, I need to work with Customers. The part that should show the list of customers, or the details of a specific customer, are working fine.
However, when I am trying to add a new customer to the database, the app crashes.

The full quote of the error:

The parameters dictionary contains a null entry for parameter ‘id’ of non-nullable type ‘System.Int32’ for method ‘System.Web.Mvc.ActionResult CustomerDetails(Int32)’ in ‘VidlyExercise1.Controllers.CustomersController’. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

I’ve trying to copy the exact code from lessons, but still something doesn’t match.

The Customers Controller code:

    public class CustomersController : Controller
{
    private ApplicationDbContext _context;

    public CustomersController()
    {
        _context = new ApplicationDbContext();
    }

    protected override void Dispose(bool Disposing)
    {
        _context.Dispose();
    }

    // GET: Customers
    [Route("customers")]

    public ActionResult CustomersList()
    {
        var customers = _context.Customers.Include(c => c.MembershipType).ToList();

        var viewModel = new CustomersIndexViewModel
        {
            Customers = customers
        };

        return View(viewModel);
    }

    [Route("customers/{id}")]
    public ActionResult CustomerDetails(int id)
    {
        var customer = _context.Customers.Include(m => m.MembershipType)
            .SingleOrDefault(c => c.Id == id); //Eager loading 

        var viewModel = new CustomerDetailsViewModel
        {
            Name = customer.Name,
            MembershipType = customer.MembershipType,
            Birthdate = customer.Birthdate
        };

        return View(viewModel);
    }

    [Route("customers/new")]
    public ActionResult New()
    {
        var membershipTypes = _context.MembershipTypes.ToList();

        var viewModel = new NewCustomerViewModel()
        {
            MembershipTypes = membershipTypes,
            Customer = new Customer()
        };

        return View("New", viewModel);
    }

    [HttpPost]
    public ActionResult Create(Customer customer)
    {
        _context.Customers.Add(customer);
        _context.SaveChanges();

        return RedirectToAction("CustomersList", "Customers");
    }

Now, when I click the button just to enter the View for adding a new Customer, it opens up fine.
But when I try to click the “Save” button, I get an error I posted above.
I even tried, changing the code in “Create” method, even just to post 404.

return HttpNotFound();

So, as I understand the Create method doesn’t even get to the part of doing anything, it just crashes.

Here’s the View code:

@model VidlyExercise1.ViewModels.NewCustomerViewModel
@{
    ViewBag.Title = "New";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>New Customer</h2>
@using (Html.BeginForm("Create", "Customers", FormMethod.Get))
{
    <div class="form-group">
        @Html.LabelFor(m => m.Customer.Name)
        @Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control" })
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Customer.Birthdate)
        @Html.TextBoxFor(m => m.Customer.Birthdate, new { @class = "form-control" })
    </div>
    <div class="form-group">
        <label>
            @Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsLetter) Subscribed to newsletter
        </label>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Customer.MembershipTypeId)
        @Html.DropDownListFor(m => m.Customer.MembershipTypeId, 
            new SelectList(Model.MembershipTypes, "Id", "Name"),
            "Select Membership Types", new { @class = "form-control" })
    </div>
    @Html.HiddenFor(m=>m.Customer.Id)
    <button type="submit" class="btn btn-primary">Save</button>
}

I think the example code from mentor on GitHub is almost identical. The View html is different, because it also includes further lessons, but the Controller code seems to be correct.

I know the there is a need to post something I already tried. I did google for potential fixes, and did try some of them, but the problem is, I don’t know what I am looking for.

Some examples of what I found in similar questions, but which didn’t help:

@using (Html.BeginForm("Search", "Person",FormMethod.Get))

Don’t use a variable “Id” in ActionResult CustomerList: I never used one

Maybe something else I don’t remember now.

One more thing: When I click the button, the path shows: “localhostCustomersCreate”

There is no View suited for this, and I am not sure that it’s what supposed to happen.

Can you please help to find what’s wrong? Again, it’s hard to find an error myself, since I only recently started learning ASP.NET (with the said course) and new to it.

And one more question: The “create” button should get a “Customer” from somewhere, but where in the View code I actually “send” it?

Thank you in advance,

Evgenie

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I apologize for trouble, I seems I found what was the problem.
Upon clicking “Save” button, the route was trying to redirect to “customer/save”.

And there was a line:

public ActionResult CustomerDetails(int)

So, the program was trying to open route “customer/save” as if the word “save” was an Id!
So, instead of even getting to the code in the ActionResult Save, it tried to find a customer with non-existing Id=”Save”.
To fix that, all I needed is to change the line declaring the ActionResult CustomerDetails, that it will only accept integers as an Id’s.

Like this:

    [Route("customers/{id:int}")]
    public ActionResult CustomerDetails(int id)

I didn’t have to do any changes to “Save” method in CustomersController, or to the relevant View.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x