繁体   English   中英

当我使用 JQuery.ajax() 方法将用户凭据发布到 C# controller 时,为什么会收到 HTTP 400(错误请求)错误? (ASP.NET Mvc 红隼)

[英]Why I'm getting a HTTP 400 (bad request) error when I'm posting user credentials with JQuery .ajax() method, to a C# controller? (ASP.NET Mvc Kestrel)

介绍一下我有什么

你好,所以我想在 C# 中创建一个 Kestrel web 应用程序,它根据用户通过填写 HTML 页面中的输入框提供的信息来注册用户。

重要文件/类

该页面位于名为“wwwroot”的文件夹中,该文件夹位于应用程序的根目录中。 具有 JQuery 语法的文件内容如下所示:

<!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 class="container">
            <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" class="registerbtn" id="regbtn">Register</button>
        </div>

        <div class="container signin">
            <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>

这不是唯一的 html 页面...但我认为在这个问题上无关紧要。 它只是一个样板寄存器 window。

通过注册,我的意思是我想将这些凭据放入一个名为 database.db 的数据库文件中,就这么简单......这是 SQL 语法,以便您了解结构:

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

我只创建了两个单元格,因为我还不想处理太多数据。 此数据库文件位于名为 Database 的文件夹中,该文件夹位于应用程序的根目录中。 我需要将 Sqlite 与 EntityFramework 一起使用,因为我的教授说我们不能使用 PHP 和任何其他类似的。 我正在使用“SQLite 数据库浏览器”检查数据。

所以我在一个名为 Controllers 的文件夹中创建了一个 SessionController class,该文件夹位于应用程序的根目录中:

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");
        }
    }
}

这个 controller 只是一个简单的:建立连接,创建一个 SQL 命令然后在打开的数据库上执行它,关闭数据库然后将用户重定向到指定的 HTML 页面。

好吧,我在这个文件夹中还有另一个 controller class,它叫做 HomeController:

using Microsoft.AspNetCore.Mvc;

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

当应用程序加载时,这将重定向到登录 HTML 页面。

关于启动应用程序的类...我在应用程序的根目录中的一个单独的 C# 文件中有一个程序和一个启动 class。 程序 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>();
            });
    }
}

这个 class 构建应用程序,然后在中间件所在的 Startup class 的帮助下运行它。 启动 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" }
                );
            });

            
        }
    }
}

有了这个启动页面加载(又名 login.html )。

问题

问题是,当我单击调用 JQuery.ajax() 方法的 register.html 上的注册按钮时,我收到 HTTP 400(错误请求)错误。 请参见下面的屏幕截图:

在此处输入图像描述

我试过什么?

所以我首先尝试传递用户在 ajax 方法中输入的基本值(我没有对输入数据进行字符串化),然后......我得到了同样的错误。 然后我在 SessionController class 中的 AddUserToDatabase 方法上面指定了一个属性标记,它告诉它消耗什么类型的数据:

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

这给了我一个不同的错误...不支持的媒体类型(HTTP 415 错误)。 接下来我做的......我在 ajax 方法中指定了数据和内容类型,只是在方法末尾添加:

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

再次出现同样的错误。

在此之后我被卡住了,我不知道从这一点开始在 web 上移动到哪里,或者我应该做什么。

能否请您告诉我应该声明或做出不同的哪些内容,并提供一些提示或资源来告诉我我做错了什么? 提前致谢!

只需更改您发布的数据格式,如下所示:

$('#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);
        }
    });
});

后端代码应如下所示:

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

顺便说一句,Ajax 无法处理服务器端重定向,您需要在ajax.success() function 中使用window.location.href ,如下所示:

$.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);
    }
});

后端代码应如下所示:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM