从另一个控制器(Web API)将新记录发布到AspNetUsers

时间:2019-04-04 14:19:41

标签: asp.net asp.net-web-api asp.net-core

我想使用webApi将新用户发布到AspNetUsers 这是我想做的事情: [HttpPost]

        public async Task<IHttpActionResult> POST([FromBody]ICollection<ApplicationUser> employees)
        {

        employees.First().PasswordHash = HashPassword(employees.First().PasswordHash);

        if (!ModelState.IsValid)
            {

                return BadRequest(ModelState);
            }


        foreach (var item in employees)
        {
            db.Users.Add(item);
        }
        try
        {
            await db.SaveChangesAsync();
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            Exception raise = dbEx;
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                    // raise a new exception nesting
                    // the current instance as InnerException
                    raise = new InvalidOperationException(message, raise);
                }
            }
            throw raise;
        }
        var manager = new UserManager<ApplicationUser, int>
        (new CustomUserStore(new ApplicationDbContext()));

        var roleManager = new RoleManager<CustomRole, int>
            (new CustomRoleStore(new ApplicationDbContext()));
        manager.AddToRoles(employees.First().Id, "User");

        return CreatedAtRoute("DefaultApi", new { id = employees.First().Id  }, employees);
    }
    public static string HashPassword(string password)
    {
        if (password == null)
        {
            throw new ArgumentNullException("password");
        }


        byte[] salt;
        byte[] subkey;
        using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
        {
            salt = deriveBytes.Salt;
            subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
        }

        var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
        Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
        Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
        return Convert.ToBase64String(outputBytes);
    }

我尝试使用Postman进行测试,这就是我得到的:

**** [ArgumentNullException]:值不能为null。 参数名称:值    在System.Security.Claims.Claim..ctor中(字符串类型,字符串值,字符串valueType,字符串发行者,字符串originalIssuer,ClaimsIdentity主题,字符串propertyKey,字符串propertyValue)    在System.Security.Claims.Claim..ctor处(字符串类型,字符串值)    在Microsoft.AspNet.Identity.ClaimsIdentityFactory 2.<CreateAsync>d__19.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter 1.GetResult()    在C:\ DataInGrid \ DataInGrid \ Models \ IdentityModels.cs:line 18中的DataInGrid.Models.ApplicationUser.d__0.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter 1.GetResult() at DataInGrid.Providers.ApplicationOAuthProvider.<GrantResourceOwnerCredentials>d__2.MoveNext() in C:\DataInGrid\DataInGrid\Providers\ApplicationOAuthProvider.cs:line 42 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler.<InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync>d__3f.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler.<InvokeTokenEndpointAsync>d__22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler.<InvokeAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware 1.d__0.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)    Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware 1.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware 1.d__0.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)    在Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware 2.<Invoke>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware 2.d__5.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)    在Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.d__5.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)    在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)    在Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.d__2.MoveNext() ---从之前引发异常的位置开始的堆栈结束跟踪---    在Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar)    在Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar)    在System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()    在System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep步骤)    在System.Web.HttpApplication.ExecuteStep(IExecutionStep步骤,布尔值和完成同步) -> ****

1 个答案:

答案 0 :(得分:0)

您的代码很混乱。我不确定您在做什么。首先,UserManagerRoleManager是服务。您永远不会更新它们;相反,您将它们注入到班级中:

[ApiController]
public UserApiController : ControllerBase
{
    private readonly UserManager<ApplicationUser> _userManager;

    public UserApiController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    ...
}

然后,要创建新用户,您应该使用:

await _userManager.CreateAsync(user, password);

这将为您散列密码,以及其他必要的任务,例如规范用户名,电子邮件地址等。

接下来,您不应该将帖子绑定到ApplicationUser。那是您的实体,不适用于创建用户请求之类的东西。即,它没有Password属性来保存用户所需的密码(已预先加密)。而是应仅使用要提交的属性来创建视图模型/ DTO类。可能只有一个电子邮件地址和一个密码。

然后,您将发布的数据映射到ApplicationUser实体的实例上:

var user = new ApplicationUser
{
    Email = model.Email
    // etc.
};

然后:

await _userManager.CreateAsync(user, model.Password);

由于要发布要创建的用户列表,因此只需对其进行迭代,并对每个用户执行相同的操作。