InvalidOperationException:不正确的内容类型:ASP.NET Core
Posted
技术标签:
【中文标题】InvalidOperationException:不正确的内容类型:ASP.NET Core【英文标题】:InvalidOperationException: Incorrect Content-Type: ASP.NET Core 【发布时间】:2018-07-18 05:35:38 【问题描述】:我有两种形式,一种用于登录,一种用于注册。它们都在相同的视图上并使用相同的模型。我正在使用控制器处理表单提交。
访问登录页面时出现以下错误
InvalidOperationException: Incorrect Content-Type:
完整的错误日志:https://pastebin.com/JjfDtr6q
我在网上查看过,找不到与我的问题直接相关的任何内容,而且我在 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 Microsoft.AspNetCore.Mvc;
using PastPapers.Models;
namespace PastPapers.Controllers
public class LoginController : Controller
public IActionResult Index(LoginModel loginModel = null)
if (loginModel == null)
return View();
else
return View(loginModel);
[HttpPost]
public IActionResult AttemptLogin(LoginModel loginModel = null)
if (loginModel != null)
loginModel.AttemptLogin();
if (loginModel.loginSuccess)
return RedirectToAction("Index", "Home", null);
else
return RedirectToAction("Index", loginModel);
else
return RedirectToAction("Index");
[HttpPost]
public IActionResult AttemptRegister(LoginModel loginModel = null)
if (loginModel != null)
loginModel.AttemptRegister();
if (loginModel.registerSuccess)
return RedirectToAction("Index");
else
return RedirectToAction("Index", loginModel);
else
return RedirectToAction("Index");
我的模型
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);
【问题讨论】:
为什么你的LoginModel
继承自HttpContextAccessor
?我知道你在哪里使用它,但它几乎肯定会成为你问题的原因。
这样我就可以访问 HTTP 变量来设置用户名等。在模型中访问会话变量的正确方法是什么?
【参考方案1】:
我会放弃 HttpContextAccessor(或者更确切地说是 IHttpContextAccessor)的全部继承,因为您将失去具体 HttpContextAccessor 提供的功能。相反,将 HttpContextAccessor 注入控制器,然后使用登录模型上的操作结果来设置会话值。像这样:
在您的Startup.ConfigureServices
中添加这一行:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
这使得 HttpContext 能够被注入到控制器中。
然后在你的控制器中,添加一个接受 IHttpContextAccessor 的构造函数:
public LoginController(IHttpContextAccessor contextAccessor)
// save to a field, like _httpContext = contextAccessor.HttpContext;
然后将该 HttpContext 作为参数传递给LoginModel.AttemptLogin
。这样您仍然可以满足访问 HTTP 变量的要求,并且代码更易于维护和预测。
有一个警告 - 将 HttpContextAccessor 添加到服务中会降低性能。但总体来说更好。
【讨论】:
根据 MS 文档,切勿将 HttpContext 保存到字段中,只能将访问器本身保存。 docs.microsoft.com/en-us/aspnet/core/performance/…【参考方案2】:将 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);
【讨论】:
以上是关于InvalidOperationException:不正确的内容类型:ASP.NET Core的主要内容,如果未能解决你的问题,请参考以下文章
InvalidOperationException:未找到名为“Bearer”的 AuthorizationPolicy
为啥这个 OdbcConnection 会抛出 System.InvalidOperationException?
System.InvalidOperationException: '绑定实例已经被关联到监听
使用 PerformanceCounters 时获取 InvalidOperationException [关闭]