Search code examples
c#asp.net-corerazor

ASP NET Core Web API project, Send Values from form to controller


I decided to learn ASP.NET Core and I started by build a web page from scratch using the template ASP.NET Core Web API. I created a folder called Pages in my project where I added a razor page called Index.cshtml, in that razor page I have a form that lets a client enter a name and a query into text fields. I then added a new folder called Controllers to this project and added a file called FormController which has a method that is supposed to handle the data entered into the form by the user. I then gave the two input fields the same names as the parameter names in the method that should handle them in the FormController file but when I submit the form, the error HTTP 400 This page is not working now. My form uses the post method to send values to the controller, here is the HTML markup for the form that I am using to capture input from the user.

  <form onsubmit="return false;" method="post" asp-route="Form" asp-controller="FormController"  asp-action="GetAction" id="form">
    <div class="form-group">
       <label for="name">Name</label>
       <input type="text" name="name" class="form-control" id="name" placeholder="Enter your name" asp-for="Name">
    </div>
    <div class="form-group">
       <label for="query">Query</label>
       <textarea class="form-control" name="query" id="query" style="margin-top:20px" rows="5" placeholder="Enter your query" asp-for="Description"></textarea>
    </div> 
</form>

The controller that is supposed to be receiving these values from the form looks like this.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace ASPLearner.Controllers
{
    [Route("api/[controller]",Name = "Form")]
    [ApiController]
    public class FormController : ControllerBase
    {
        //indicate to the method that we only need http post
        [HttpPost]
        public IActionResult GetAction(string name, string query)
        {
           
            // Redirect to a success page or return a response
            return RedirectToAction("Success");
        }
    }
}

I have also added support for MVC and mapped the controllers in my Startup C# code as shown below.

using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
//configure the services before calling the builder.build
IServiceCollection services = builder.Services;
//add controllers with views
services.AddControllersWithViews(); 
services.AddMvc();  
//add all the razor pages
services.AddRazorPages();
var app = builder.Build();
//alow static styling files to be loaded from wwwroot
app.UseStaticFiles();  
//add https redirection
app.UseHttpsRedirection();  
//add routing for the razor pages
app.UseRouting();
app.MapRazorPages();
app.MapFallbackToPage("/Index");
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
app.UseAuthorization(); 
app.Run();

The form shows up in a modal but when I fill random values and hit send, the page shown in the screenshot is displayed, help me get rid of the error so the values are successfully posted to the controller.

before enter image description here


Solution

    1. I don't think you could send the request with onsubmit="return false;"

    2. asp-route="Form" asp-controller="FormController" asp-action="GetAction" would result confliction

      asp-route="Form

    would attach the parttern /api/[controller] name of Form to the action attribute of form (html element)

    asp-controller="FormController"  asp-action="GetAction"
    

    would attach /FormController/GetAction to action attribute

    You should remove asp-controller="FormController" asp-action="GetAction",

    3,If your controller is attached with [ApiController] attribute,it would bind

    data from request body instead of request form,and when failed model validation,it would return 400 directly,you have to add [FromForm] attribute

    You could check this document related,try modify as below

    public IActionResult GetAction([FromForm]string name, [FromForm]string query)
            {
    
                // Redirect to a success page or return a response
                .....
            }
    

    Codes in View:

    <form  method="post" asp-route="Form" id="form">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" name="name" class="form-control" id="name" placeholder="Enter your name" asp-for="Name">
        </div>
        <div class="form-group">
            <label for="query">Query</label>
            <textarea class="form-control" name="query" id="query" style="margin-top:20px" rows="5" placeholder="Enter your query" asp-for="Description"></textarea>
        </div>
        <div class="form-group">
            <input type="submit" value="Submit"/>
        </div>
    </form>
    

    Result:

    enter image description here

    Tried with modal as you expected:

        <div id="dialog" class="modal" tabindex="-1">
        <div class="modal-dialog modal-xl">
        <div class="modal-content">
            <form method="post" asp-route="Form" id="form">
                <div class="modal-header">
                    <label for="name">Name</label>
                    <input type="text" name="name" class="form-control" id="name" placeholder="Enter your name" asp-for="Name">
                </div>
                <div class="modal-body d-grid gap-3">
                    <label for="query">Query</label>
                    <textarea class="form-control" name="query" id="query" style="margin-top:20px" rows="5" placeholder="Enter your query" asp-for="Description"></textarea>
                </div>
                <div class="modal-footer">
                    <input type="submit" value="Submit" />
                </div>
            </form>
        </div>
        </div>
        
    </div>
    
    <button id="opendialog">Open Dialog</button>
    
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script>
        $(function () {
          
            $("#opendialog").click(function () {
                $("#dialog").modal('show')
            });
        });
    </script>
    

    Result: enter image description here

    It doesn't matter,please show the codes related with sending request and press F12,select NetWork and check the request you've sent

    enter image description here

    Program.cs:

    .....
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    app.MapRazorPages();
    
    app.MapFallbackToPage("/Index");
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    app.Run();