无法将用户添加到Roles Web Api

时间:2018-05-21 10:19:57

标签: c# asp.net asp.net-mvc asp.net-web-api2

我正在开发一个项目,该项目要求用户具有某些角色来限制对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>();
    }
}

1 个答案:

答案 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

的上下文