问题
I am trying to do two things here:
1. Adding an email field to the (default)UserProfile table. Works like a charm. Users can register both a username and email.
2. Change the login to use the email instead of username, this does also works like a charm.
Here is the problem. The above only works when i seperate them, as soon as I use both of them the registration process fails with the following error message:
Cannot insert the value NULL into column 'UserName', table 'opdb.dbo.UserProfile'; column does not allow nulls. INSERT fails.
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Email = model.Email
});
WebSecurity.Login(model.Email, model.Password);
I am more or less following the guide found here, In the comments section I see others having the same problem, however, the solution is not to set the UserName field to allow nulls as stated in the replies.
The strange thing is that everything works as long as I don't use both together. Any ideas? This drives me crazy!
Thanks in advance
Edit: Could it be the order of columns in the database? That the field used for identification needs to be the first column in the table? So if I want email as ident that need to be the first column in the table?
回答1:
It is not the column order. I think you haven't set your WebSecurity.InitializeDatabaseConnection up properly. It sounds like when you add the email field, it is treated as the email field (and not the natural key for the users), and when you change the login to use the email, you are actually inserting the email into the UserName column?
Either way, it is simple to make work. Assuming you already have your email column in the database and you are using the standard Internet Application template, do the following:
- Change your
UserProfilemodel to add anEmailproperty, do the same to theRegisterModeland change theLoginmodel fromUserNametoEmail - Update the
InitializeSimpleMembershipAttributeto use Email instead ofUserNameas the natural key for the users - Update the
AccountControllerLoginandRegisteractions so you capture a UserName and an Email on registration, and use the Email on login - Update the views
So, the actual changes to make are:
- Models/AccountModels.cs changes
class UserProfile: add the propertypublic string Email { get; set; }class LoginModel: change the property name fromUserNametoEmailclass RegisterModel: add the propertypublic string Email { get; set; }and set its attributes toRequired, set theDisplay(Nameetc. (max length if you want to enforce that as well
AccountControllerchangesLoginmethod:- Change
model.UserNametomodel.Emailin the lineif (ModelState.IsValid && WebSecurity.Login(model.UserName ...
- Change
Registermethod:- Change
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);toWebSecurity.CreateUserAndAccount(model.Email, model.Password, new { UserName = model.UserName }); - EDIT - missed a change:
Change
WebSecurity.Login(model.UserName, model.Password);toWebSecurity.Login(model.Email, model.Password);
- Change
- Filters/InitializeSimpleMembershipAttribute.cs changes
- Change
"UserName"to"Email"inWebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
- Change
- Views/Account/Login.cshtml
- Change the three usages of
m.UserNametom.Email
- Change the three usages of
- Views/Account/Register.cshtml
- Copy and paste the UserName
<li>section and change the duplicatesm.UserNametom.Email
- Copy and paste the UserName
In a vanilla Internet Application MVC 4 project, these changes will work perfectly (in a true vanilla project you may have to apply migrations if you want to use these and you aren't editing the database to add the Email column).
回答2:
I am not sure if Andy Browns suggestion will work because the WebSecurity in namespace WebMatrix.WebData references will not work correctly as a result. They are specifically looking at the UserName field to perform their actions. I could be wrong, but that's my perception. If you want a separate field, create another username field (Name) and run your own code to update that to reflect to the user.
I chose to set up a registration view that renamed the UserName to User Email
<li>
@Html.Label("Email Address:")
@Html.TextBoxFor(m => m.UserName)
</li>
and then in the Login and Register model simply required the user name entered as an email format using:
[Required]
[DataType(DataType.EmailAddress)]
[EmailAddress]
[Display(Name = "UserEmail")]
public string UserName { get; set; }
Maybe too simplistic, but it works for me.
来源:https://stackoverflow.com/questions/16529469/simplemembership-adding-email-field-and-use-as-login-name