C# InvalidOperationException:不正确的内容类型:ASP.NET核心
我有两个表格,一个用于登录,一个用于注册。它们都位于同一视图上,并且使用相同的模型。我正在和管理员一起处理表单提交 我在访问登录页面时遇到以下错误C# InvalidOperationException:不正确的内容类型:ASP.NET核心,c#,asp.net,asp.net-core,.net-core,C#,Asp.net,Asp.net Core,.net Core,我有两个表格,一个用于登录,一个用于注册。它们都位于同一视图上,并且使用相同的模型。我正在和管理员一起处理表单提交 我在访问登录页面时遇到以下错误 InvalidOperationException: Incorrect Content-Type: 完整错误日志: 我在网上查过,找不到任何与我的问题直接相关的东西,而且我在C#/.NET Core方面的经验不足,无法理解导致问题的原因 我的看法 @model PastPapers.Models.LoginModel @{ Layout
InvalidOperationException: Incorrect Content-Type:
完整错误日志:
我在网上查过,找不到任何与我的问题直接相关的东西,而且我在C#/.NET Core方面的经验不足,无法理解导致问题的原因
我的看法
@model PastPapers.Models.LoginModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
<!-- Register form inside modal -->
<div id="registerModal" class="">
<div class="">
<header class="">
<span onclick="document.getElementById('registerModal').style.display = 'none'" class="">×</span>
<h2>Register</h2>
</header>
<div class="">
<form asp-controller="Login" asp-action="AttemptRegister" method="post">
<input asp-for="newUsername" type="text" placeholder="Username" />
<input asp-for="newEmail" type="email" placeholder="Email" />
<input asp-for="newPassword" type="password" placeholder="Password" />
<input type="submit" value="Register" />
</form>
</div>
</div>
</div>
<!-- Login form -->
<form asp-controller="Login" asp-action="AttemptLogin" method="post">
<input asp-for="username" type="text" placeholder="Username" />
<input asp-for="password" type="password" placeholder="Password" />
<input type="submit" value="Login" />
</form>
<button onclick="document.getElementById('registerModal').style.display='block'" class="">Register</button>
</body>
</html>
我的模型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using PastPapers.Helpers;
using Microsoft.AspNetCore.Http;
namespace PastPapers.Models
{
public class LoginModel : HttpContextAccessor
{
public string username { get; set; }
public string password { get; set; }
public bool loginSuccess { get; set; }
public string loginErrorMessage { get; set; }
public string newUsername { get; set; }
public string newPassword { get; set; }
public string newEmail { get; set; }
public bool registerSuccess { get; set; }
public string registerErrorMessage { get; set; }
[JsonIgnore]
public AppDb Db { get; set; }
public LoginModel(AppDb db = null)
{
Db = db;
loginSuccess = false;
registerSuccess = false;
}
public LoginModel()
{
}
public void AttemptRegister()
{
try
{
Db.Connection.Open();
string sql = "INSERT INTO users (id, username, password, email) VALUES (DEFAULT, @username, @password, @email)";
MySqlCommand cmd = new MySqlCommand(sql, Db.Connection);
cmd.Prepare();
cmd.Parameters.AddWithValue("@username", newUsername);
cmd.Parameters.AddWithValue("@password", SecurePasswordHasher.Hash(newPassword));
cmd.Parameters.AddWithValue("@email", newEmail);
if (cmd.ExecuteNonQuery() == 0)
{
System.Diagnostics.Debug.WriteLine("Account failed to create!");
registerSuccess = false;
} else
{
registerSuccess = true;
}
} catch (Exception ex)
{
registerErrorMessage = "Error connecting to database";
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
public void AttemptLogin()
{
try
{
Db.Connection.Open();
string sql = "SELECT password FROM users WHERE username=@username";
MySqlCommand cmd = new MySqlCommand(sql, Db.Connection);
cmd.Prepare();
cmd.Parameters.AddWithValue("@username", username);
MySqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
string dbPassword = reader.GetString(0);
if (SecurePasswordHasher.Verify(password, dbPassword))
{
loginSuccess = true;
HttpContext.Session.SetString("username", username);
} else
{
loginSuccess = false;
loginErrorMessage = "Incorrect password";
}
} else
{
loginErrorMessage = "Unknown username";
}
} catch (Exception ex)
{
loginErrorMessage = "Error connecting to database";
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
}
将HttpContextAccessor的继承替换为IHttpContextAccessor,并添加了公共HttpContext属性。新型号如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using PastPapers.Helpers;
using Microsoft.AspNetCore.Http;
namespace PastPapers.Models
{
public class LoginModel : IHttpContextAccessor
{
public string username { get; set; }
public string password { get; set; }
public bool loginSuccess { get; set; }
public string loginErrorMessage { get; set; }
public string newUsername { get; set; }
public string newPassword { get; set; }
public string newEmail { get; set; }
public bool registerSuccess { get; set; }
public string registerErrorMessage { get; set; }
[JsonIgnore]
public AppDb Db { get; set; }
public HttpContext HttpContext { get; set; }
public LoginModel(AppDb db = null)
{
Db = db;
loginSuccess = false;
registerSuccess = false;
}
public LoginModel()
{
}
public void AttemptRegister()
{
try
{
Db.Connection.Open();
string sql = "INSERT INTO users (id, username, password, email) VALUES (DEFAULT, @username, @password, @email)";
MySqlCommand cmd = new MySqlCommand(sql, Db.Connection);
cmd.Prepare();
cmd.Parameters.AddWithValue("@username", newUsername);
cmd.Parameters.AddWithValue("@password", SecurePasswordHasher.Hash(newPassword));
cmd.Parameters.AddWithValue("@email", newEmail);
if (cmd.ExecuteNonQuery() == 0)
{
System.Diagnostics.Debug.WriteLine("Account failed to create!");
registerSuccess = false;
} else
{
registerSuccess = true;
}
} catch (Exception ex)
{
registerErrorMessage = "Error connecting to database";
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
public void AttemptLogin()
{
try
{
Db.Connection.Open();
string sql = "SELECT password FROM users WHERE username=@username";
MySqlCommand cmd = new MySqlCommand(sql, Db.Connection);
cmd.Prepare();
cmd.Parameters.AddWithValue("@username", username);
MySqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
string dbPassword = reader.GetString(0);
if (SecurePasswordHasher.Verify(password, dbPassword))
{
loginSuccess = true;
HttpContext.Session.SetString("username", username);
} else
{
loginSuccess = false;
loginErrorMessage = "Incorrect password";
}
} else
{
loginErrorMessage = "Unknown username";
}
} catch (Exception ex)
{
loginErrorMessage = "Error connecting to database";
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
}
我将放弃HttpContextAccessor(或者更确切地说是IHttpContextAccessor)的全部继承,因为您将失去具体HttpContextAccessor提供的功能。相反,将HttpContextAccessor注入控制器,然后使用登录模型上的操作结果来设置会话值。像这样: 在
启动.ConfigureServices
中添加此行:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
然后将HttpContext作为参数传递到LoginModel.AttemptLogin
。这样,您仍然可以满足访问HTTP变量的需求,并且代码更易于维护和预测
有一个警告-将HttpContextAccessor添加到服务中会对性能造成小的影响。但是总的来说更好。为什么您的
LoginModel
继承自HttpContextAccessor
?我知道您在哪里使用它,但这几乎肯定是您问题的原因。这样我就可以访问HTTP变量来设置用户名等。访问模型中会话变量的正确方法是什么?根据MS文档,永远不要将HttpContext保存到字段中,而只保存访问器本身。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
public LoginController(IHttpContextAccessor contextAccessor)
{
// save to a field, like _httpContext = contextAccessor.HttpContext;
}