'Why my form does not pass parameters to my controller?

I am trying to pass values entered by a user in a form to an ASP.NET MVC controller for processing to a database context. I do not know why the values in the form are not being passed to the controller method with the same parameter names, because when I try to submit the form, it does nothing. Please help me do this correctly to pass entries from the form to the controller.

This is my controller code:

using Cars.Models;
using Microsoft.AspNetCore.Mvc;

namespace Cars.Controllers
{
    public class CarController : Controller
    {
        //declare the reference to database
        CarsContext _context ;

        public CarController()
        {
            _context = new CarsContext();
        }

        [HttpPost]
        //this method is supposed to receive the form values
        //and insert into the database
        public void GetProperties(string make, string model, string year, string nop)
        {
            // create a new car object
            Car car = new Car()
            {
                Make = make,
                Model = model,
                Year = Int32.Parse(year),
                NoPassengers = Int32.Parse(nop)
            };

            // create a new database context
            _context.Add(car);

            // save changes
            _context.SaveChanges();
        }

        // method to get all the cars
        public List<Car> GetAllCars()
        {
            // create a new database context
            return _context.Car.ToList();
        }

        // method to get a car by id
        public Car? GetById(int? id)
        {
            return _context.Car.FirstOrDefault(c => c.Id == id);
        }

        // method to check if a car exists
        public bool Exists(Car obj)
        {
            return _context.Car.Where(c => c.Id == obj.Id).Any();
        }

        // return cars whose passenger seats is three or less
        public List<Car> ThreePassengers()
        {
            return _context.Car.Where(c => c.NoPassengers <= 3).ToList();  
        }
    }
}

This is my index.cshtml view with the values I need passed to the controller via parameters

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Car Property Editor</h1>
   <p>Fill out the details of the car in the form below </p>
   <br/>
   <br/>
   @using (Html.BeginForm("GetProperties", "CarController"))
   {
   <table class="table">
     <thead>
         <tr>
             <td>Make</td>
             <td>Model</td>
             <td>Year Manufactured</td>
             <td>Number of Passengers</td>
         </tr>
     </thead>
     <tbody>
         <tr>
             <td>@Html.TextBox("make")</td>
               <td>@Html.TextBox("model")</td>
                 <td>@Html.TextBox("year")</td>
                   <td>@Html.TextBox("nop")</td>

         </tr>
     </tbody>
     <br/>

   </table>
    <center><input class="btn" type="submit" value="Insert"asp-action="myfunction()" style="background:blue;color:#111"></center>
   }
   <button class="btn">Get All Cars</button>
   <button class="btn">Get Car  by Id</button>
   <button class="btn">Get Car with three passenger seats</button>
   <button class="btn">Sort Cars by year manufactured</button>
</div>


Solution 1:[1]

  1. You need know that you mix ASP.NET Core MVC with ASP.NET Core Razor Pages in your project. You can see your frontend uses @page which is used in Razor Pages, but your backend code is public class CarController : Controller which is used in MVC.

  2. You use @using (Html.BeginForm("GetProperties", "CarController")), the second parameter matches controller name, just use Car instead of CarController.

  3. @using (Html.BeginForm("GetProperties", "CarController")) will generate the html code like below, so no need add extra asp-action="ActionName".

    <form action="/Car/GetProperties" method="post">   
        //other html code....
    </form>
    

Above all, change your frontend code like below:

@page
@model IndexModel
<div class="text-center">
    <h1 class="display-4">Car Property Editor</h1>
   <p>Fill out the details of the car in the form below </p>
   <br/>
   <br/>
   @using (Html.BeginForm("GetProperties", "Car"))
   {
   <table class="table">
     <thead>
         <tr>
             <td>Make</td>
             <td>Model</td>
             <td>Year Manufactured</td>
             <td>Number of Passengers</td>
         </tr>
     </thead>
     <tbody>
         <tr>
             <td>@Html.TextBox("make")</td>
               <td>@Html.TextBox("model")</td>
                 <td>@Html.TextBox("year")</td>
                   <td>@Html.TextBox("nop")</td>

         </tr>
     </tbody>
     <br/>

   </table>
    <center><input class="btn" type="submit" value="Insert" style="background:blue;color:#111"></center>
   }
   <button class="btn">Get All Cars</button>
   <button class="btn">Get Car  by Id</button>
   <button class="btn">Get Car with three passenger seats</button>
   <button class="btn">Sort Cars by year manufactured</button>
</div>

Be sure add MVC route template in Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {  
        //other middlewares.....
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");   //add this.....
           
        });
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rena