我有一个带有寄存器方法的 ASP.net API 2应用程序,它基本上执行以下操作:
var user = new ApplicationUser() { UserName = user.email, Email = user.email };
UserManager.AddToRole(user.Id, "SomeRole");
在同一个控制器中,我想为应用程序用户分配一个模型类,例如:
var parent = db.Parents.Find(parentToCreate.id);
db.SaveChanges();
这给了我一个错误,即用户名已被占用。我知道问题与有两个模型跟踪器有关,一个用于UserManager.CreateAsync
,一个用于更新数据库。是否可以在不使用CreateAsync
的情况下创建用户,或者是否有其他方法可以避免此错误?
请注意,我认为这可以通过在帐户属性上放置父属性来实现,但并非所有帐户都是父帐户,因此我不想执行此解决方案。父级有一个帐户,因此父级上有一个帐户属性。
根据要求,完整注册方法如下:
[AllowAnonymous]
[Route("RegisterParent")]
public async Task<IHttpActionResult>RegisterParent(ParentRegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.email, Email = model.email };
Parent parentToCreate = new Parent();
db.Parents.Add(parentToCreate);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.SaveChanges();
try
{
IdentityResult result = await UserManager.CreateAsync(user, model.password);
// The following two lines give an error
parentToCreate.account = user;
// the above two lines give an error
UserManager.AddToRole(user.Id, "ParentRole");
db.SaveChanges();
}
catch (Exception e)
{
Console.Write(e);
// e returns here with message
}
return Ok(200);
}
这是一个基于OP中提供的最小示例的简化示例。
基于对话以澄清当前设计,需要更新Parent
模型以首先具有正确的代码外键关系
public class Parent {
//...other properties
//Foreign key
public string accountid { get; set; }
//navigation property
[ForeignKey("accountid")]
public ApplicationUser account { get; set; }
}
这样,您只需要在创建父级时分配用户 ID。
重构/抽象出特定职责。
public interface IParentService {
Task AddParentAsync(ApplicationUser user);
}
public class ParentService : IParentService {
ApplicationDbContext db;
public ParentService(ApplicationDbContext db) {
this.db = db;
}
public async Task AddParentAsync(ApplicationUser user) {
Parent parentToCreate = new Parent() {
//...set other properties
accountid = user.Id
};
db.Parents.Add(parentToCreate);
await db.SaveChangesAsync();
}
}
接下来,将操作分成不同的进程以避免并发问题。
public class AccountController : ApiController {
ApplicationUserManager userManager;
IParentService parentService;
public AccountController(ApplicationUserManager userManager, IParentService parentService) {
this.userManager = userManager;
this.parentService = parentService;
}
[AllowAnonymous]
[Route("RegisterParent")]
public async Task<IHttpActionResult> RegisterParent(ParentRegisterBindingModel model) {
if (!ModelState.IsValid) {
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.email, Email = model.email };
var result = await userManager.CreateAsync(user, model.password);
if (result.Succeed) {
try {
await userManager.AddToRole(user.Id, "ParentRole");
await parentService.AddParentAsync(user);
return Ok();
} catch (Exception e) {
userManager.Delete(user.Id);
Console.Write(e);
// e returns here with message
return BadRequest(); //OR InternalServerError();
}
} else {
foreach (var error in result.Errors) {
ModelState.AddModelError("", error);
}
return BadRequest(ModelState);
}
}
}
显然,您将向 DI 框架注册依赖项以允许正确的注入。