ASP.NET MVC Custom Membership Provider "CreateUser"
I've implemented some basic, custom membership provider for my ASP.NET MVC application so I thought that all validation will be done in my custom code.
Unfortunately when I'm trying to create new user by calling function:
Membership.CreateUser(user.UserName, user.Password, user.Email, null, null, true, Guid.NewGuid(), out status);
which should eventually throw an exception with all validation errors I'm getting a status like "InvalidUserName" or "InvalidPassword" instead... That means that my custom CreateUser function isn't call directly, it's used after some basic validation which I would wish to skip.
My CreateUser function (in my custom provider):
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
try
{
User user = new User();
user.UserKey = Guid.NewGuid();
user.UserName = username;
user.passwordSalt = string.Empty;
user.Password = this.TransformPassword(password, ref user.passwordSalt);
user.Email = email;
user.PasswordQuestion = passwordQuestion;
user.PasswordAnswer = passwordAnswer;
user.CreationDate = DateTime.Now;
user.LastActivityDate = DateTime.Now;
user.LastLoginDate = DateTime.MinValue;
user.LastPasswordChangeDate = DateTime.Now;
this._UsersRepository.SaveUser(user);
status = MembershipCreateStatus.Success;
return CreateMembershipFromInternalUser(user);
}
catch(RuleException ex)
{
throw ex;
}
}
Do you know how to enforce direct usage of custom CreateUser function !?
But I'm not using a default ASP.NET MVC project's AccountController...
Just take a look:
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Register(User user, string password_confirm, bool acceptsTerms)
{
if (!acceptsTerms)
ModelState.AddModelError("acceptsTerms", "Musisz zaakceptować regu开发者_如何学Golamin");
if (ModelState.IsValid)
{
try
{
MembershipCreateStatus status = new MembershipCreateStatus();
Membership.CreateUser(user.UserName, user.Password, user.Email, null, null, true, Guid.NewGuid(), out status);
}
catch (RuleException ex){
ex.CopyToModelState(ModelState,"user");
}
}
return View();
}
The point is that I'm getting a status instead of RuleException ex when user.UserName or user.Password is empty. My custom RuleException ex would give me back such informations as well. Where a status value is assigned right now !? Bacouse it's not done in my implementation of CreateUser...
I am using this (MVC3) and I have no issues:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
MembershipCreateStatus status;
Membership.Provider.CreateUser(model.UserName, model.Password, model.Email, "", "", true, Guid.NewGuid(), out status);
if (status == MembershipCreateStatus.Success)
{
FormsService.SignIn(model.UserName, false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", AccountValidation.ErrorCodeToString(status));
}
}
// If we got this far, something failed, redisplay form
ViewBag.PasswordLength = MembershipService.MinPasswordLength;
return View(model);
}
Using ILSpy to view the static method Membership.CreateUser, you will find it performs validation on
- Username (trim whitespace + not null, not empty)
- Password (trim whitespace + not null, not empty, length checks)
- Email (trim whitespace)
- Password Question (trim whitespace + not empty)
- Password Answer (trim whitespace + not empty)
It then calls the custom provider.
The key here is to not call the static method CreateUser
Membership.CreateUser(...)
Rather, call the custom provider directly by using:
Membership.Provider.CreateUser(...)
Tested and verified working, as of .NET 4
While my site recommends having a password, we support openid. So forcing a user to have a password just seemed counter to what openid is good for.
Complete rewrite
The ASP.NET Membership system always does some initial validation of the inputs when APIs such as CreateUser are called.
I don't know of any way around this aside from not going directly to the ASP.NET membership APIs.
精彩评论