【问题标题】:Identity UpdateAsync lose IdentityResult.FailedIdentity UpdateAsync 丢失 IdentityResult.Failed
【发布时间】:2014-03-04 14:03:12
【问题描述】:

我为 ASP.NET Identity 编写了一个自定义 UserStore,我在 ASP.NET MVC 5.1 应用程序中使用它。一切都按预期工作,我对 ASP.NET 的这个新功能(身份)非常满意......

问题是我想已经快 2 天了,因为我试图从 UpdateAsync 方法返回一个错误,但不知何故,我似乎无法返回任何东西。

LE:我正在使用 ASP.NET Identity Core 2.0.0-beta1

这是我的几行代码:

public Task UpdateAsync(IdentityUser user)
{
    AdminUserEntity userEntity = new AdminUserEntity();
    userEntity.IsNew = false;
    userEntity.Id = user.UserModel.Id;
    userEntity.UserCompleteName = user.UserModel.UserCompleteName;
    userEntity.IsDisabled = user.UserModel.IsDisabled;

    if (!String.IsNullOrEmpty(user.UserModel.PasswordHash))
        userEntity.PasswordHash = user.UserModel.PasswordHash;

    if (user.Claims != null && user.Claims.Count > 0)
    {
        foreach (Claim claim in user.Claims)
        {
            AdminUserClaimEntity claimEntity = userEntity.AdminUserClaims.AddNew();
            claimEntity.AdminUserUniqueId = user.UserModel.UniqueId;
            claimEntity.ClaimType = claim.Type;
            claimEntity.ClaimValue = claim.Value;
        }
    }

    try
    {
        byte[] timestamp = Convert.FromBase64String(user.UserModel.Timestamp);
        AdminUserEntityManagement.UpdateCompleteAdminUserEntity(userEntity, timestamp);
    }
    catch (Exception exception)
    {
        List<string> errors = new List<string>() {exception.Message};
        return Task.FromResult<IdentityResult>(IdentityResult.Failed(errors.ToArray()));
    }

    return Task.FromResult<object>(null);
}

虽然发生了异常并且正在执行 catch 块,但以下行总是返回成功:

IdentityResult result = await UserManager.UpdateAsync(identityUser);

谁能告诉我我错过了什么?

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-identity


    【解决方案1】:

    我假设这个 UpdateAsync 在你的 ApplicationUserManager 类中,签名不应该是

    public override Task<IdentityResult> UpdateAsync 
    

    如果您尝试更改 UserManager 的 UpdateAsync 方法的工作方式。

    【讨论】:

    • 否 - UpdateAsync 取自 UserStore 类,该类实现了必要的接口(公共类 UserStore:IUserStore、IUserClaimStore、IUserLoginStore、IUserRoleStore、IUserPasswordStore 、IUserSecurityStampStore)。
    • 嗯,那就解释一下,UserManager 和 UserStore 之间的合同是例外,如果在您想要返回 identityResult 的地方发生了不好的事情,您需要在 Usermanager 级别进行处理。 UserManager 假定如果没有引发异常,则更新操作成功完成。如果要捕获异常并将其转换为 IdentityResult.Failures 并出现在应用程序中,则必须在 UserManager 上覆盖此行为。
    • 那我还有两个问题:a) 这意味着我必须实现自己的UserManager?如果是,为什么?我问这个是因为据我了解,UserManager 是 UserStore、RoleStore 等之上的一层,不需要用自定义实现覆盖; b) 为什么在不使用该值的情况下 UpdateAsync 方法仍然有一个返回参数?谢谢!
    • 您不必重新实现,您可以根据需要扩展和覆盖一个方法,它没有返回参数,Task 是 void 的异步等效项。
    • 所以,我将 UserManager 扩展为一个名为 AdminUserManager 的类,并在公共覆盖 Task UpdateAsync(IdentityUser user) 中放置了 base.UpdateAsync(user);进入 try / catch 块......根本没有捕捉到异常......知道为什么吗?谢谢。
    【解决方案2】:

    首先,@hao-kung,感谢您的帮助。现在我可以说我已经看到了大局。虽然我不能说我喜欢它,但我了解 UserManager 的工作原理。

    另外,如果你觉得我说错了,请纠正我。

    对于其他人,为了自定义 UserManager 行为(即使您只是想显示一个无论如何都可以在 UserStore 自定义类中捕获的错误),您必须遵循这些步骤(为了更好地理解,我将举例说明描述我为捕获 UpdateAsync 方法的业务异常并将其显示在界面中所做的工作):

    1. 在 UserStore 类(它应该在其他接口中实现 IUserStore 接口)中,不要捕获任何异常。

      public Task UpdateAsync(IdentityUser user)
      {
          // here an exception will be thrown if there is a concurrency issue
          byte[] timestamp = Convert.FromBase64String(user.UserModel.Timestamp);
          AdminUserEntityManagement.UpdateCompleteAdminUserEntity(userEntity, timestamp);
          return Task.FromResult<object>(null);
      }
      
    2. 扩展 UserManager 类,重写你要自定义的方法(捕获之前抛出的业务异常,并在接口上浮现):

      public class AdminUserManager : UserManager<IdentityUser>
      
      
      public override async Task<IdentityResult> UpdateAsync(IdentityUser user)
      {
          Task<IdentityResult> result = base.UpdateAsync(user);
      
          try
          {
              IdentityResult identityResult = await result;
          }
          catch (Exception exception)
          {
              List<string> errors = new List<string>() { exception.Message };
              return IdentityResult.Failed(errors.ToArray());
          }
      
          return result.Result;
      }
      
    3. 在 MVC 控制器中(例如)从扩展的 UserManager 类中读取 UpdateAsync 方法的结果:

      IdentityResult result = await UserManager.UpdateAsync(identityUser);
      if (result.Succeeded)
      {
        this.SetNotification("The user has been updated.", EnumToastrNotificationType.Info);
        return RedirectToAction("ShowUsers", "UserManagement");
      }
      else
      {
        this.AddErrors(result);
      }
      

    【讨论】:

      猜你喜欢
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      相关资源
      最近更新 更多