Dan*_*ary 9 .net f# asp.net-identity asp.net-core
我正在用F#构建一个.NET核心Web应用程序,我正在尝试设置Identity.我有一个基本版本的Register方法,它在数据库中创建一个用户并创建cookie:
[<HttpPost>]
[<AllowAnonymous>]
member this.Register([<FromBody>]model: RegisterViewModel) =
if not (isNull model.Email) && model.Password = model.ConfirmPassword then
let user = ApplicationUser(userName = model.Email, email = model.Email, password = model.Password)
let result = userManager.CreateAsync(user, model.Password) |> Async.AwaitTask |> Async.RunSynchronously
if result.Succeeded then
signInManager.SignInAsync(user, isPersistent = false) |> Async.AwaitTask |> Async.RunSynchronously
true
else
false
else
false
Run Code Online (Sandbox Code Playgroud)
但是,我的Login实现挂起:
[<HttpPost>]
[<AllowAnonymous>]
member this.Login([<FromBody>]model: LoginViewModel) =
if not (isNull model.Email && isNull model.Password) then
let result = signInManager.PasswordSignInAsync(model.Email, model.Password, false, lockoutOnFailure = false) |> Async.AwaitTask |> Async.RunSynchronously
if result.Succeeded then true else false
else
false
Run Code Online (Sandbox Code Playgroud)
这是应用程序挂起的地方:
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (5ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u].[Email], [u].[EmailConfirmed], [u].[LockoutEnabled], [u].[LockoutEnd], [u].[NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled], [u].[UserName]
FROM [AspNetUsers] AS [u]
WHERE [u].[NormalizedUserName] = @__normalizedUserName_0
Run Code Online (Sandbox Code Playgroud)
知道问题可能是什么?
根据这篇文章,处理程序可以是async(在 C# 意义上),因此将路由处理程序重写为非阻塞是有意义的,从而消除Async.RunSynchronously可能导致问题的问题。
我们可以在 F# 工作流程中编写实际逻辑async,因为这更加自动化,然后将其转换为 aTask<_>以匹配预期的 C# 签名。
[<HttpPost>]
[<AllowAnonymous>]
member this.Login([<FromBody>]model: LoginViewModel) =
async {
if not (isNull model.Email && isNull model.Password)
then
let! result =
signInManager.PasswordSignInAsync(model.Email, model.Password, false, lockoutOnFailure = false)
|> Async.AwaitTask
return result.Succeeded
else
return false
}
|> Async.StartAsTask
Run Code Online (Sandbox Code Playgroud)
死锁很难找到,因此在使用 F# 时,您应该尝试在应用程序中async仅调用一次,通常是在“main”方法中。Async.RunSynchronously