Adding fields to webpages_Membership SimpleMembershipProvider - ef-code-first

Is it possible to add fields/columns to webpages_Membership?
[Table("webpages_Membership")]
public class Membership
{
public Membership()
{
Roles = new List<Role>();
OAuthMemberships = new List<OAuthMembership>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UserId { get; set; }
public DateTime? CreateDate { get; set; }
[StringLength(128)]
public string ConfirmationToken { get; set; }
public bool? IsConfirmed { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
[Required, StringLength(128)]
public string Password { get; set; }
public DateTime? PasswordChangedDate { get; set; }
[Required, StringLength(128)]
public string PasswordSalt { get; set; }
[StringLength(128)]
public string PasswordVerificationToken { get; set; }
public DateTime? PasswordVerificationTokenExpirationDate { get; set; }
public ICollection<Role> Roles { get; set; }
[ForeignKey("UserId")]
public ICollection<OAuthMembership> OAuthMemberships { get; set; }
}
I want to add LogonCount as a field/column, but this table gets filled automatically by the membership provider upon creating a CreateUserAndAccount().
I don't seem to have any influence on giving the LogonCount a value at CreateUserAndAccount().

The standard way to add information relevant to a given userId is in the UserProfile table, not the webpages_Membership table. See my answer here and Jon Galloway's post on "SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates" for more info about how SimpleMembership ties together with UserProfile.
I don't seem to have any influence on giving the LogonCount a value ...
You then access the UserProfile table and information through your database context, not through the membership provider, which is really there to give you access to a core set of features only.
using (MyDbContext db = new MyDbContext())
{
UserProfile user = db.UserProfiles
.First(u => u.UserName.ToLower() == model.UserName.ToLower());
user.LogonCount = 1;
db.SaveChanges();
}

Related

ASP.NET Core Conflict with Foreign Key

I have got several models:
Course.cs
public class Course
{
public Guid Id { get; set; }
public ICollection<ApplicationUser> Teacher { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public DateTime CreationDate { get; set; }
public bool IsActive { get; set; }
}
Group.cs
public class Group
{
public Guid Id { get; set; }
public ApplicationUser Mentor { get; set;}
public string DisplayName { get; set; }
public string GroupName { get; set; }
public DateTime StartYear { get; set; }
public string InviteCode { get; set; }
public ICollection<ApplicationUser> Students { get; set; }
public ICollection<Course> Courses { get; set; }
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
[Required]
public string Firstname { get; set; }
[Required]
public string Surname { get; set; }
public bool Gender { get; set; }
public DateTime Birthdate { get; set; }
//[Required]
public string InviteCode { get; set; }
public Guid GroupId { get; set; }
[ForeignKey("GroupId")]
public Group CurrentGroup { get; set; }
public ICollection<Group> PastGroups { get; set; }
}
Now when I try to register (using Identity) a user (not even trying to give the user a group) I receive this error:
SqlException: The INSERT statement conflicted with the FOREIGN KEY
constraint "FK_AspNetUsers_Groups_GroupId". The conflict occurred in
database "aspnet-Project_Dojo-3af15f80-8c62-40a6-9850-ee7a296d0726",
table "dbo.Groups", column 'Id'. The statement has been terminated.
In my modelBuilder I have added some logics for the relations between Group, ApplicationUser (Students) and the Foreign Key:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);\\
builder.Entity<ApplicationUser>()
.HasOne(p => p.CurrentGroup)
.WithMany(b => b.Students)
.HasForeignKey(p => p.GroupId);
}
I don't know what this is exactly doing, but I've been browsing some Stackoverflow threads to come to this code (migrations weren't working without it).
I look forward to a solution for my problem. Once again, I'm not doing ANYTHING with the groups yet when registering.
Thanks in advance!
not even trying to give the user a group
Well there's your problem, it's required.
Either provide a group, or make it optional by making the foreign key nullable (Guid? GroupId).
Because it's currently a non-nullable struct, it'll have a default value of all zeroes (Guid.Empty). This FK is not known in your database, resulting in the error you see.

Creating Relational Tables in Entity Framework

I am trying to build a pretty extensive database heavy web application and doing so with little experience. What I am trying to figure out is creating a relational table in entity framework through scaffolding.
It seems I have accidentally done this already with these two models, but I have no idea how it happened:
namespace FlavorPing.Models
{
public class MenuItem
{
[Key]
public int MenuItemID { get; set; }
public string ItemName { get; set; }
public string Description { get; set; }
//Category
//May need to put this back and add to controllers and views.
//[ForeignKey("Merchant")]
//public int MerchantID { get; set; }
public virtual Merchant Merchant { get; set; }
public ICollection<Follower> Followers { get; set; }
}
}
public class Merchant
{
//Meant to inherit identity.
[ForeignKey("ApplicationUserId")]
public string ApplicationUserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
[Key]
public int MerchantID { get; set; }
[Required]
[Display(Name = "Business Name")]
public string MerchantName { get; set; }
[Required]
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string email { get; set; }
//need to create formatting here.
[Required]
[Display(Name = "Web Site Link")]
public string website { get; set; }
public int MenuItemID { get; set; }
public virtual List<MenuItem> MenuItems { get; set; }
public virtual MerchantDetails MerchantDetails { get; set; }
}
The above models have their own dedicated tables, but a second table MenuItemFollowers was created with the MenuItemID and FollowerID as columuns, which I want, but I have no idea how I did this and need to know so I could add another ID to this table.

ASP.NET Identity for WebForms - getting started with extending User attributes

I'm working on my first ASP.NET WebForms project using Identity. I ticked the box when creating the project and the basics all seem to be working OK. Now I want to extend the Register form and the AspNetUsers table with new attributes (e.g. Users (actual) Name). I'd also like to expose the existing PhoneNumber attribute.
I did some research but couldn't find any non-MVC info on this scenario. Is the expectation that I just hack away at the template code to achieve this?
I'm happy to do so, just wondering if I am missing something...
As you say you are using an ASP.NET Web From with default files and folders.
Please open the IdentityMode.cs in Models folder and find ApplicationUser class.
In this class you can add user attributes as properties, see example :
01: add profile information in users table:
public class ApplicationUser : IdentityUser
{
[Required]
public string UserFullName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNumber { get; set; }
[Required]
public string Address { get; set; }
public DateTime RegisteredDate { get; set; }
public string Info { get; set; }
}
02 :
you can add profile information in different table :
public class ApplicationUser : IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
}
public class UserInfo
{
[Required]
public string UserFullName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNumber { get; set; }
[Required]
public string Address { get; set; }
public DateTime RegisteredDate { get; set; }
public string Info { get; set; }
}

Problems when using EF Reverse POCO Generator generated models

I'm using asp.net default membership provider to create a website.
I used 'EF Reverse POCO Generator' and got some csharp code of build-in membership tables, I removed some classes and kept only Applications, Memberships, Profiles, Roles and Users.
The problem is I cannot use them because of exceptions throwing when the database is initialized.
The first exception I encountered is complaining missing the primary key, I added [Key] annotation to the primary field, problem solved.
Then I got the second error seems complaining missing foreign keys:
Unable to determine the principal end of an association between the types 'GoHome.Models.Memberships' and 'GoHome.Models.Users'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Looks like can be solved by adding [ForeignKey], but after that I still got the third one, which I cannot find a solution in Google:
*Introducing FOREIGN KEY constraint 'FK_dbo.RolesUsers_dbo.Users_Users_UserId' on table 'RolesUsers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.*
Quite odd, as looks to me there is no table called 'RolesUsers' at all.
I only added two [ForeignKey] in Memberships and Profiles respectively, which resulted in the third error. Here is the code:
// Memberships
public class Memberships
{
//[ForeignKey("Applications")]
public Guid ApplicationId { get; set; } // ApplicationId
[Key]
[ForeignKey("Users")]
public Guid UserId { get; set; } // UserId (Primary key)
public string Password { get; set; } // Password
public int PasswordFormat { get; set; } // PasswordFormat
public string PasswordSalt { get; set; } // PasswordSalt
public string Email { get; set; } // Email
public string PasswordQuestion { get; set; } // PasswordQuestion
public string PasswordAnswer { get; set; } // PasswordAnswer
public bool IsApproved { get; set; } // IsApproved
public bool IsLockedOut { get; set; } // IsLockedOut
public DateTime CreateDate { get; set; } // CreateDate
public DateTime LastLoginDate { get; set; } // LastLoginDate
public DateTime LastPasswordChangedDate { get; set; } // LastPasswordChangedDate
public DateTime LastLockoutDate { get; set; } // LastLockoutDate
public int FailedPasswordAttemptCount { get; set; } // FailedPasswordAttemptCount
public DateTime FailedPasswordAttemptWindowStart { get; set; } // FailedPasswordAttemptWindowStart
public int FailedPasswordAnswerAttemptCount { get; set; } // FailedPasswordAnswerAttemptCount
public DateTime FailedPasswordAnswerAttemptWindowsStart { get; set; } // FailedPasswordAnswerAttemptWindowsStart
public string Comment { get; set; } // Comment
// Foreign keys
public virtual Applications Applications { get; set; } // MembershipApplication
public virtual Users Users { get; set; } // MembershipUser
}
// Profiles
public class Profiles
{
[Key]
[ForeignKey("Users")]
public Guid UserId { get; set; } // UserId (Primary key)
public string PropertyNames { get; set; } // PropertyNames
public string PropertyValueStrings { get; set; } // PropertyValueStrings
public byte[] PropertyValueBinary { get; set; } // PropertyValueBinary
public DateTime LastUpdatedDate { get; set; } // LastUpdatedDate
// Foreign keys
public virtual Users Users { get; set; } // UserProfile
}

convert ASp.net membership provider classes to code first entities in entity framework

I am using entity frame work code first approach to design my web application in asp.net 4.5.
I have converted all asp.net membership related tables in code first entities as below
public class Application
{
public string ApplicationName { get; set; }
[Key]
public System.Guid ApplicationId { get; set; }
public string Description { get; set; }
public virtual ICollection<Membership> Memberships { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class Membership
{
[ForeignKey("Application")]
public System.Guid ApplicationId { get; set; }
[Key, ForeignKey("User")]
public System.Guid UserId { get; set; }
public string Password { get; set; }
public int PasswordFormat { get; set; }
public string PasswordSalt { get; set; }
public string Email { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
public bool IsApproved { get; set; }
public bool IsLockedOut { get; set; }
public System.DateTime CreateDate { get; set; }
public System.DateTime LastLoginDate { get; set; }
public System.DateTime LastPasswordChangedDate { get; set; }
public System.DateTime LastLockoutDate { get; set; }
public int FailedPasswordAttemptCount { get; set; }
public System.DateTime FailedPasswordAttemptWindowStart { get; set; }
public int FailedPasswordAnswerAttemptCount { get; set; }
public System.DateTime FailedPasswordAnswerAttemptWindowsStart { get; set; }
public string Comment { get; set; }
public virtual Application Application { get; set; }
public virtual User User { get; set; }
}
public class Profile
{
[Key, ForeignKey("User")]
public System.Guid UserId { get; set; }
public string PropertyNames { get; set; }
public string PropertyValueStrings { get; set; }
public byte[] PropertyValueBinary { get; set; }
public System.DateTime LastUpdatedDate { get; set; }
public virtual User User { get; set; }
}
public class Role
{
[ForeignKey("Application")]
public System.Guid ApplicationId { get; set; }
[Key]
public System.Guid RoleId { get; set; }
public string RoleName { get; set; }
public string Description { get; set; }
public virtual Application Application { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class User
{
[ForeignKey("Application")]
public System.Guid ApplicationId { get; set; }
[Key]
public System.Guid UserId { get; set; }
public string UserName { get; set; }
public bool IsAnonymous { get; set; }
public System.DateTime LastActivityDate { get; set; }
public virtual Application Application { get; set; }
public virtual Membership Membership { get; set; }
public virtual Profile Profile { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
My Datacontext and initalizer classes are as below
public class TrainningInitializer : DropCreateDatabaseIfModelChanges<TrainningContext>
{
protected override void Seed(TrainningContext context)
{
}
}
public partial class TrainningContext : DbContext
{
public TrainningContext()
: base("name=TrainningContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
public DbSet<Application> Applications { get; set; }
public DbSet<Membership> Memberships { get; set; }
public DbSet<Profile> Profiles { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
}
I am setting Initializer as below in application_start event inside Global.asax.
Database.SetInitializer<TrainningContext>(new TrainningInitializer());
But when I am running my application I am getting below error
Introducing FOREIGN KEY constraint 'FK_dbo.RoleUsers_dbo.Users_User_UserId' on table 'RoleUsers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
Can someone please help in correcting my entity classes.
When you delete an Application entity this delete cascades to the Roles and the Users and then from Roles to the RoleUsers join table and from the Users to RoleUsers. Those two delete paths from Application to RoleUsers table are the "multiple cascade paths" the exception is talking about. They are not allowed in SQL Server.
Cascading delete is enabled by default for the Roles and Users relationships of Application because the foreign key ApplicationId in these two tables is not nullable, hence the relationship is required. Required relationships have cascading delete turned on by default.
But you can turn it off with Fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Application>()
.HasMany(a => a.Roles)
.WithRequired(r => r.Application)
.HasForeignKey(r => r.ApplicationId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Application>()
.HasMany(a => a.Users)
.WithRequired(u => u.Application)
.HasForeignKey(u => u.ApplicationId)
.WillCascadeOnDelete(false);
}
(It's probably sufficient for one of the two.)
If you would delete an Application entity now, you need to delete the related Roles and Users as well. The database won't do that automatically for you anymore.

Resources