InvalidOperationException:不正确的内容类型:ASP.NET核心

时间:2018-02-07 19:48:37

标签: c# asp.net asp.net-core .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="">&times;</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>

完整错误日志:https://pastebin.com/JjfDtr6q

我看过网上找不到任何与我的问题直接相关的内容,而且在C#/ .NET Core中没有足够的经验来了解造成问题的原因。

我的观点

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

        }
    }
}

我的模特

.sidenav-container {
  height: 100%;
  background-image: url("../../images/background.jpg");
}

.app-content {
  padding: 10px;
  height: calc(100% - 84px);
}

mat-card {
  border-radius: 1px;
  padding: 20px;
}

.toolbar {
  background-color: rgba(0, 0, 0, 0.5);
}

.themathon-text {
  background-color: rgba(42,42,42,.7);
}

2 个答案:

答案 0 :(得分:4)

我放弃了HttpContextAccessor(或者更确切地说是IHttpContextAccessor)的整个继承,因为你将失去具体的HttpContextAccessor提供的功能。相反,将HttpContextAccessor注入控制器,然后使用Login模型上的操作结果来设置会话值。像这样:

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添加到服务中会有很小的性能损失。但总的来说它更好。

答案 1 :(得分:0)

用IHttpContextAccessor替换了HttpContextAccessor的继承,并添加了一个公共的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);
            }

        }
    }
}