EF核心|输入字符串不是正确的格式,但我没有向整数解析任何字符串?

发布于 2025-01-31 20:28:51 字数 7400 浏览 6 评论 0原文

我正在尝试在API控制器中验证用户名和密码。

private User? Authenticate(UserLogin userLogin)
{
    string username = userLogin.Username;
    string password = userLogin.Password;

    var currentUser = _db.User.FirstOrDefault(a =>
        a.Username.ToLower() == username.ToLower() &&
        a.Password == password
    );

    if (currentUser != null)
    {
        return currentUser;
    }

    return null;
}

上述功能在此API控制器端点中使用:

[AllowAnonymous]
[HttpPost("Login")]
public IActionResult Login([FromBody] UserLogin userLogin)
{
    var user = Authenticate(userLogin);
    if (user != null)
    {
        var token = Generate(user);
        return Ok(token);
    }

    return BadRequest("User not found");
}

我的实体模型如下:

public class UserLogin : IdBase
{
    [Column(TypeName = "nvarchar(60)")]
    [Required(ErrorMessage = "Username field is required.")]
    public string Username { get; set; }
    [Column(TypeName = "nvarchar(128)")]
    [Required(ErrorMessage = "Password field is required.")]
    public string Password { get; set; }
}
public class User : UserLogin
{
    [Column(TypeName = "nvarchar(70)")]
    [Required(ErrorMessage = "Name field is required.")]
    public string Name { get; set; }
    [Column(TypeName = "nvarchar(255)")]
    [Required(ErrorMessage = "Email field is required.")]
    public string Email { get; set; }
    [Column(TypeName = "text")]
    [Required(ErrorMessage = "Email field is required.")]
    public string AssignedRole { get; set; }
}

奇数行为,我不理解:

用户名和密码匹配数据库中的内容时,返回以下例外对我的Postman:

System.FormateXception:输入字符串不是正确的格式。

当用户名和密码 不匹配数据库中的内容时,我会收到预期的400不良请求“找不到用户”:

返回badrequest(“未找到用户”);

重要的是:

当我更改查询以从列表中读取而不是从这样的数据库中读取:

var currentUser = UserConstant.Users.FirstOrDefault(a =>
                a.Username.ToLower() == username.ToLower() &&
                a.Password == password

其中userconstant是类型用户的静态列表:

public class UserConstant
{
    public static List<User> Users = new List<User>()
    {
        new User()
        {
            Name = "***",
            Username = "***",
            Email = "***",
            Password = "***",
            AssignedRole = "***"
        },
        new User()
        {
            Name = "***",
            Username = "***",
            Email = "***",
            Password = "***",
            AssignedRole = "***"
        }
    };
}

该代码按预期工作,对用户进行了认证,并且在Postman中返回我的象征。

为什么我写这个问题?

我在多个网站上看到了有关上述例外的许多问题。但是,大多数(如果不是全部)关于这个问题的目的是试图解析不包含任何有效整数进入整数的人。

据我所知,我的情况是我这样做的。

我使用的模型中的每个属性都是类型string,并且具有nvarcharch的数据注释,除了分配了 用户模型中的属性,该模型具有text> text的数据注释。

这反映在我的数据库中的用户表的列中:

“数据库列”

因此,对于为什么我会遇到这个问题,这完全超出了我。我最好的猜测是,在实体框架下有一些抽象的东西试图将输入字符串解析为整数,但我不知道会有什么情况EF来执行此操作。

更新:

idbase类:

public class IdBase
{
    [Key]
    [Column(TypeName = "nvarchar(36)")]
    [Required(ErrorMessage = "Id field is required.")]
    public int Id { get; set; }
}

_db.user.tolist()返回相同的例外:

system.formatexception:Input String不正确格式

完整堆栈跟踪:

System.FormatException: Input string was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
   at lambda_method24(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
   at lambda_method25(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at AssetBlox.Controllers.LoginController.Authenticate(UserLogin userLogin) in D:\GitHub\AssetBlox\Controllers\LoginController.cs:line 66
   at AssetBlox.Controllers.LoginController.Login(UserLogin userLogin) in D:\GitHub\AssetBlox\Controllers\LoginController.cs:line 28
   at lambda_method19(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I am trying to authenticate a username and password in my API controller.

private User? Authenticate(UserLogin userLogin)
{
    string username = userLogin.Username;
    string password = userLogin.Password;

    var currentUser = _db.User.FirstOrDefault(a =>
        a.Username.ToLower() == username.ToLower() &&
        a.Password == password
    );

    if (currentUser != null)
    {
        return currentUser;
    }

    return null;
}

The above function is used in this API controller endpoint:

[AllowAnonymous]
[HttpPost("Login")]
public IActionResult Login([FromBody] UserLogin userLogin)
{
    var user = Authenticate(userLogin);
    if (user != null)
    {
        var token = Generate(user);
        return Ok(token);
    }

    return BadRequest("User not found");
}

My entity models are as follows:

public class UserLogin : IdBase
{
    [Column(TypeName = "nvarchar(60)")]
    [Required(ErrorMessage = "Username field is required.")]
    public string Username { get; set; }
    [Column(TypeName = "nvarchar(128)")]
    [Required(ErrorMessage = "Password field is required.")]
    public string Password { get; set; }
}
public class User : UserLogin
{
    [Column(TypeName = "nvarchar(70)")]
    [Required(ErrorMessage = "Name field is required.")]
    public string Name { get; set; }
    [Column(TypeName = "nvarchar(255)")]
    [Required(ErrorMessage = "Email field is required.")]
    public string Email { get; set; }
    [Column(TypeName = "text")]
    [Required(ErrorMessage = "Email field is required.")]
    public string AssignedRole { get; set; }
}

Odd behaviour that I do not understand:

When the username and password match what exists in the database, the following exception is returned to me in Postman:

System.FormatException: Input string was not in a correct format.

When the username and password do not match what exists in the database, I receive the expected 400 Bad Request "User not found" from the line:

return BadRequest("User not found");

Important thing to note:

When I change the query to read from a list instead of from the database like this:

var currentUser = UserConstant.Users.FirstOrDefault(a =>
                a.Username.ToLower() == username.ToLower() &&
                a.Password == password

Where UserConstant is a static list of type User:

public class UserConstant
{
    public static List<User> Users = new List<User>()
    {
        new User()
        {
            Name = "***",
            Username = "***",
            Email = "***",
            Password = "***",
            AssignedRole = "***"
        },
        new User()
        {
            Name = "***",
            Username = "***",
            Email = "***",
            Password = "***",
            AssignedRole = "***"
        }
    };
}

The code works as expected, authenticating the user and returning a token to me in Postman.

Why am I writing this question?

I have seen a lot of questions across multiple sites about the above exception. However most, if not all of what I have looked at concerning this issue is people trying to parse strings that do not contain any valid integers into integers.

As far as I am aware, nowhere in my case do I do such thing.

Every single property in the models I have used is of type string and has a data annotation of nvarchar with the exception of the AssignedRole property in the User model which has a data annotation of text.

This is reflected in the columns of the User table within my database:

database columns

Therefore, it is completely beyond me as to why I am experiencing this issue. My best guess is that there is something abstracted beneath Entity Framework that is trying to parse the input string to an integer but I have not a clue what would case EF to do this.

Update:

IdBase class:

public class IdBase
{
    [Key]
    [Column(TypeName = "nvarchar(36)")]
    [Required(ErrorMessage = "Id field is required.")]
    public int Id { get; set; }
}

_db.User.ToList() returns the same exception:

System.FormatException: Input string was not in a correct format

Full stack trace:

System.FormatException: Input string was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
   at lambda_method24(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
   at lambda_method25(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at AssetBlox.Controllers.LoginController.Authenticate(UserLogin userLogin) in D:\GitHub\AssetBlox\Controllers\LoginController.cs:line 66
   at AssetBlox.Controllers.LoginController.Login(UserLogin userLogin) in D:\GitHub\AssetBlox\Controllers\LoginController.cs:line 28
   at lambda_method19(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

GRAY°灰色天空 2025-02-07 20:28:52

似乎您在实体模型中使用了nvarchar,并且在数据库中使用了varchar。并使用NVARCHAR定义了您的ID字段,该字段在数据库和实体模型中都应在int或长度上长。因此,您可以在进行此轻微更改后检查一下。

seems like you have used nvarchar in your entity model and varchar in database. And also defined your id field with nvarchar which should be int or long both in database and entity model. so can you please check after making this minor change.

酒解孤独 2025-02-07 20:28:51

从您的查询中删除tolower()

var currentUser = UserConstant.Users.FirstOrDefault(a =>
            a.Username == username &&
            a.Password == password);

SQL中的文本比较不敏感,并且您可能在表中没有一些null用户名。

remove ToLower() from your query:

var currentUser = UserConstant.Users.FirstOrDefault(a =>
            a.Username == username &&
            a.Password == password);

The text comparison in SQL is not case sensitive and you probably have some null Usernames in the table where you should not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文