asp.net - 从另一个控制器 (Web api) 将新记录发布到 AspNetUsers
问题描述
我想使用 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]:值不能为空。参数名称:System.Security.Claims.Claim..ctor(String type, String value, String valueType, String issuer, String originalIssuer, ClaimsIdentity subject, String propertyKey, String propertyValue) at System.Security.Claims.Claim.. Microsoft.AspNet.Identity.ClaimsIdentityFactory 的 ctor(字符串类型,字符串值)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.HandleNonSuccessAndDebuggerNotification(Task task) 在 System.Runtime.CompilerServices 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) .TaskAwaiter1.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(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task任务)在 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.IdentityFactoryMiddleware2.<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(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task任务)在 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.d__5.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪---在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 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() 在系统。 Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) -->****布尔值&完成同步)-->****布尔值&完成同步)-->****
解决方案
你的代码是一团糟。我不确定你在做什么。首先,UserManager
是RoleManager
服务。你永远不会更新它们;相反,您将它们注入您的班级:
[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);
由于您要发布要创建的用户列表,因此您只需对其进行迭代并为每个用户执行相同的操作。
推荐阅读
- google-apps-script - onEdit(e) 当单元格值由于内置函数而改变时不生成触发事件
- javascript - 如何从对象中解构并保留相同的对象?
- sql - 如何使用 PIVOT 将 EAV 模式转换为普通模式?
- java - 您如何阅读 Spring Cloud Gateway (Webflux) POST 过滤器中的响应正文
- sql - 第 2 行的错误 1111 (HY000):组函数的使用无效
- python - 如何使用python获取所有存在的活动域
- c++ - 步进电机平稳运动
- c++ - 素数分解堆栈
- ios - UITableView 顶部被切断
- javascript - dom-to-image 包未捕获边界图像