Home > database >  Why I'm getting a HTTP 400 (bad request) error when I'm posting user credentials with JQue
Why I'm getting a HTTP 400 (bad request) error when I'm posting user credentials with JQue

Time:01-11

Introduce what I have

Hello there, so I want to create a Kestrel web application in C#, that register users based on their information that they provided by filling the input boxes in an HTML page.

Important files/classes

The page is located in a folder called "wwwroot", this folder is located in the root directory of the application. The contents of the file with the JQuery syntax looks this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="Design/registerStyle.css" />
    <script src="https://code.jquery.com/jquery-3.6.1.js" 
            integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI=" 
            crossorigin="anonymous"></script>
    <title>Register</title>
</head>
<body>
    <form>
        <div >
            <h1>Register</h1>
            <p>Please fill in this form to create an account.</p>
            <hr>
            <label for="uname"><b>User Name</b></label>
            <input type="text" placeholder="Enter Your User Name" name="uname" id="uname" required>
            
            <hr>

            <p>By creating an account you agree to our <a href="#">Terms & Privacy</a>.</p>
            <button type="button"  id="regbtn">Register</button>
        </div>

        <div >
            <p>Already have an account? <a href="login.html">Sign in</a>.</p>
        </div>
    </form>

    <script>
            $('#regbtn').click(function () {
                let user_name = $('#uname').val();
                let stringified_data = JSON.stringify(user_name);

                $.ajax({
                    url: '/session/regist',
                    type: 'POST',
                    data: stringified_data,
                    success: function (response) {
                        console.log('Success', response);
                    },
                    fail: function (failed) {
                        console.log('Failed', failed);
                    }
                });
            });
    </script>
</body>
</html>

This is not the only html page...but it doesn't matter in this problem I think. It's just a boilerplate register window.

By registration I meant that I want to put those credentials into a database file which is called database.db, simple as that...here is the SQL syntax so that you know the structure:

CREATE TABLE User (
    `UserID` INTEGER PRIMARY KEY AUTOINCREMENT
    , `UserName` TEXT NOT NULL    
)

I created just two cells, because I don't want to work with too much data yet. This database file is located in a folder named Database which is located in the root directory of the application. I need to use Sqlite with EntityFramework because my professor said that we can't use PHP and any other similiar. I'm inspecting the data using the "DB Browser for SQLite".

So I created a SessionController class in a folder named Controllers which is located in the root directory of the application:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using System.ComponentModel;

namespace WebApplication3.Controllers
{
    [ApiController]
    public class SessionController : Controller
    {
        [HttpPost, Route("/session/regist")]
        public IActionResult AddUserToDatabase([FromForm] string UserName)
        {
            try
            {
                /* Establish connection with database */
                using var connection = new SqliteConnection("Data source=database.db");
                connection.Open();
                using var command = connection.CreateCommand();
                command.CommandText = "insert into "  
                    "User "  
                    "( `UserName`) "  
                    "values "  
                    "(@username);";
                
                /* Add parameters with value */
                command.Parameters.AddWithValue("@username", UserName);

                /* Execute the SQL command and close connection */
                command.ExecuteNonQuery();
                connection.Close();
            }
            catch(Exception ex) {
                Console.WriteLine(ex.Message);
                return  Redirect("/page/registerFailed.html");
            }

            return Redirect("/page/registerSuccess.html");
        }
    }
}

This controller is just a simple one: establishes connection, creating an SQL command then executes it on the open database, closes the database then redirects the user to a specified HTML page.

Well I have another controller class in this folder, its called the HomeController:

using Microsoft.AspNetCore.Mvc;

namespace WebApplication3.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet, Route("")]
        public IActionResult Login()
        {
            return Redirect("/page/login.html");
        }
    }
}

This redirects to the login HTML page when the application loads.

About the classes that launches the application... I have a Program and a Startup class in a separate C# file, in the root directory of the application. The Program class:

using Starting.Start;

namespace Starting.Prog
{
    public class Program
    {
        /* Builds and runs the app with the help of the HostBoulder methods */
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        /* Builds the application using the Startup class */
        public static IHostBuilder CreateHostBuilder(string[] args) => 
            Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(web_builder =>
            {
                web_builder.UseStartup<Startup>();
            });
    }
}

This class builds the app and then runs it with the help of the Startup class, where the middleware is located. The Startup class:

using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.FileProviders;

namespace Starting.Start
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddMvcOptions(options =>
            {
                options.RespectBrowserAcceptHeader= true;
                options.InputFormatters.Add(new XmlSerializerInputFormatter(options));
                options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
            });
        }
        
        /* Configure the app middleware */
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            
            /* Gets the root directory */
            string root_directory = Directory.GetCurrentDirectory();

            /* Gets the directory where the html files are located */
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(root_directory, "wwwroot")),
                RequestPath = "/page"
            });

            /* Enables routing */
            app.UseRouting();
            
            /* Specifying the endpoints */
            app.UseEndpoints(endpoints =>
            {
                /* Starter page (login.html) */
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Login}"                  
                );
                
                /* Create the route for the registration method */
                endpoints.MapControllerRoute(
                    name: "Session",
                    pattern: "/session/regist",
                    defaults: new { controller = "Session", action = "AddUserToDatabase" }
                );
            });

            
        }
    }
}

With this the starter page loads ( a.k.a. the login.html ).

The problem

The problem is that when I'm clicking on the register button on the register.html which invokes the JQuery .ajax() method, I'm getting an HTTP 400 (Bad Request) error. See the screenshot below:

enter image description here

What I tried?

So I first tried to pass the basic value which the user inputs in the ajax method (I didn't stringfied the input data) and well...I got the same error. Then I specified an attribute tag above the AddUserToDatabase method in the SessionController class, which tells what type of data it consumes:

        [HttpPost, Route("/session/regist"), Consumes("application/json")]
        public IActionResult AddUserToDatabase([FromForm] string UserName)
        {      
               Here is the user registration....
        }

This gave me a different error... Unsupported media type (HTTP 415 error). The next thing I did... I specified the data and content type in the ajax method, just added at the end of the method:

     dataType: "json",
     contentType: "application/json"

Again the same error.

And after this I'm stuck, I don't know where to move on the web from this point, or what should I do.

Can you please tell me what should be declared or made differently, and provide me some tips or sources which tells me what did I wrong? Thanks in advance!

CodePudding user response:

Just change your posted data format like below:

$('#regbtn').click(function () {
    let user_name = $('#uname').val();
    let stringified_data = { UserName: user_name };  //change here....

    $.ajax({
        url: '/session/regist',
        type: 'POST',
        data: stringified_data,
        success: function (response) {
            console.log('Success', response);
        },
        fail: function (failed) {
            console.log('Failed', failed);
        }
    });
});

Backend code should keep like below:

[HttpPost, Route("/session/regist")]
public IActionResult AddUserToDatabase([FromForm] string UserName)
{ 
    //...
}

BTW, Ajax cannot handle the server side redirection, you need use window.location.href in the ajax.success() function like below:

$.ajax({
    url: '/session/regist',
    type: 'POST',
    data: stringified_data,
    success: function (response) {
        window.location.href = response.url;   //add here...
    },
    fail: function (failed) {
        console.log('Failed', failed);
    }
});

Backend code should be like below:

[HttpPost, Route("/session/regist")]
public IActionResult AddUserToDatabase([FromForm] string UserName)
{     
    //....
    return Json(new { url= "/page/registerSuccess.html" });
}
  • Related