我正在开发一个项目,该项目要求用户具有某些角色来限制对API函数的访问。 当我尝试将用户添加到给定角色时,我得到一个我不太理解的例外,因为所提到的声明是在身份内定义的。
异常和堆栈
"ClassName": "System.ArgumentException",
"Message": "The property 'Logins' on type 'ApplicationUser' is not a navigation property. The Reference and Collection methods can only be used with navigation properties. Use the Property or ComplexProperty method.",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": " at System.Data.Entity.Internal.InternalEntityEntry.ValidateAndGetNavigationMetadata(String navigationProperty, Type requestedType, Boolean requireCollection) at System.Data.Entity.Internal.InternalEntityEntry.Collection(String navigationProperty, Type requestedType) at System.Data.Entity.Infrastructure.DbEntityEntry`1.Collection[TElement](String navigationProperty) at System.Data.Entity.Infrastructure.DbEntityEntry`1.Collection[TElement](Expression`1 navigationProperty) at Microsoft.AspNet.Identity.EntityFramework.UserStore`6.AreLoginsLoaded(TUser user) at Microsoft.AspNet.Identity.EntityFramework.UserStore`6.<EnsureLoginsLoaded>d__69.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.EntityFramework.UserStore`6.<GetUserAggregateAsync>d__6c.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.TaskExtensions.CultureAwaiter`1.GetResult() at Microsoft.AspNet.Identity.UserManager`2.<AddToRoleAsync>d__83.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() at VmeRust_Server.Controllers.AccountController.<Register>d__16.MoveNext() in C:\Users\kevom\source\repos\Rust VIP Manager\VmeRust_Server\Controllers\AccountController.cs:line 205",
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": "8 ValidateAndGetNavigationMetadata EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=censored System.Data.Entity.Internal.InternalEntityEntry System.Data.Entity.Internal.NavigationEntryMetadata ValidateAndGetNavigationMetadata(System.String, System.Type, Boolean)",
"HResult": -2147024809,
"Source": "EntityFramework",
"WatsonBuckets": null,
"ParamName": null
The property 'Logins' on type 'ApplicationUser' is not a navigation property. The Reference and Collection methods can only be used with navigation properties. Use the Property or ComplexProperty method."
如果尝试创建已存在的用户
,我也会收到同样的错误注册码
// POST api/Account/Register
[System.Web.Http.AllowAnonymous]
//[System.Web.Http.Authorize(Roles = "SubscriptionManager")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser
{
UserName = model.Email,
Email = model.Email,
AccountClosed = false,
LastLoginDateUtc = DateTime.Now,
LastLoginIp = Request.GetOwinContext().Request.RemoteIpAddress,
//CreatedBy = new Guid(User.Identity.GetUserId()),
AccessFailedCount = 0,
DateCreated = DateTime.Now,
};
// Register the user
try
{
var result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
}
catch (Exception e)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, $"User was not created: {e.Message}"));
}
// Add user to Role
try
{
#if DEBUG
await UserManager.AddToRoleAsync(user.Id, VmeRoles.Developer);
#else
await UserManager.AddToRoleAsync(user.Id, VmeRoles.VmeUser);
#endif
}
catch (Exception e)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, e.Message));
}
return Ok();
}
这是上下文代码
public class ApplicationUser : IdentityUser
{
/// <summary>
/// Gets or sets the subscription
/// </summary>
public Subscription UserSubscription { get; set; }
/// <summary>
/// The date account was created
/// </summary>
public System.DateTime? DateCreated { get; set; }
/// <summary>
/// Who Created the Account
/// </summary>
public System.Guid CreatedBy { get; set; }
/// <summary>
/// Last Login activity of the account (date)
/// </summary>
public System.DateTime? LastLoginDateUtc { get; set; }
/// <summary>
/// Last login acitivity of the account (IP)
/// </summary>
public string LastLoginIp { get; set; }
/// <summary>
/// Indicates if the account is closed
/// </summary>
public bool AccountClosed { get; set; }
/// <summary>
/// Indicates the date the account was closed
/// </summary>
public System.DateTime? AccountCLosedTime { get; set; }
/// <summary>
/// Indicates if the account is pending a password reset
/// </summary>
public bool? PasswordReset { get; set; }
/// <summary>
/// Indicates if the account is pending a password reset
/// </summary>
public string PasswordResetToken { get; set; }
/// <summary>
/// Indicates if the account is pending a password reset
/// </summary>
public DateTime? PasswordResetTokenExpriry { get; set; }
/// <summary>
/// The last Login session Id
/// </summary>
public string LastSessionId { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
/// <summary>
/// A data set that contains basic information about a subcription
/// </summary>
public class Subscription
{
// Some code ...
public Guid AddedByUser { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("VmeRustDev", throwIfV1Schema: false)
{
}
/// <summary>Logins
/// Gets or sets the SubScription Data set
/// </summary>
public DbSet<Subscription> Subscription { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ApplicationUser>().ToTable("Users").HasKey(i => i.Id);
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles").HasKey(i => i.RoleId);
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims").HasKey(i => i.Id);
modelBuilder.Entity<IdentityRole>().ToTable("Roles").HasKey(i => i.Id);
modelBuilder.Ignore<IdentityUserLogin>();
}
}
答案 0 :(得分:1)
尝试将此行添加到ApplicationUser类
public ICollection<Role> Roles { get; set; }
并创建一个Role类:
public class Role : IdentityRole
{
public ICollection<ApplicationUser> Users { get; set; }
}
====使用RoleManager更新===
public class ApplicationRoleManager : RoleManager<Role>
{
public ApplicationRoleManager(IRoleStore<Role, string> store) : base(store)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
var roleStore = new RoleStore<Role>(context.Get<SecurityDbContext>());
return new ApplicationRoleManager(roleStore);
}
}
最后使用ApplicationRoleManager而不是RoleManager 注意:SecurityDbContext是继承自IdentityDbContext
的上下文