I am using Asp.net MVC to create a password and confirm password field. I am currently using the remote attribute to check if password and confirm password are the same, however remote will only call a function if the box it is applied to is changed.
I've looked through previous posts going back to last year and found the most common suggestion to be the compare attribute, however it is now deprecated.
I assume there is a pre-built solution for this problem.
This is from the model
[Remote(UserController.ActionNameConstants.PasswordMatch,
UserController.NameConst, AdditionalFields = "ConfirmPassword",
ErrorMessage = "The passwords do not match")]
[MinLength(8, ErrorMessage="Minimum password length is 8")]
[DisplayName("Password"), RequiredIf("Id == 0",
ErrorMessage="Password is required")]
public string Password { get; set; }
[DisplayName("Confirm Password"), RequiredIf("Id == 0",
ErrorMessage = "Confirm password is required")]
public string ConfirmPassword { get; set; }
This is in the controller
[HttpGet]
public virtual JsonResult PasswordMatch(string password,string confirmPassword)
{
return this.Json(password ==
confirmPassword,JsonRequestBehavior.AllowGet);
}
Compare is not depricate you can still use [Compare("Property name to compare with")]... it's in "System.ComponentModel.DataAnnotations" namespace.
Related
I have this email validation attribute
[EmailAddress]
[StringLength(50, ErrorMessage = "Email is too long!")]
public string Email { get; set; }
And it works fine, but the problem is when I type the email, and then erase it, the form still asks me to insert correct email even though the field is not required.
it will accept empty string or exact an email id
"^$|^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$"
Answer
As we know when you create an ASP.NET Core appp using Individual User Authentication project template, it creates a default ResetPassword.cshtml view. In that View I need to set logged in user name input tag as readonly. But doing so is throwing the following validation error. If I don't make it readonly the below screen successfully allows user to change password.
Question: Why the following validation error on form submit - when the UserName input tag is set to readonly? I know that if the input tag is disabled then form submit does not submit the input tag's value (also explained by #AdamBellaire here). It seems [Required] annotation in public string UserName { get; set; } is somehow conflicting with readonly attribute of input tag.
public class ResetPasswordViewModel
{
[Required]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
public string Code { get; set; }
}
UPDATE
ResetPassword.cshtml: [It's a default View created by VS2017. Only change is that I added readonly attribute in input tag below]
#model ResetPasswordViewModel
...
<input asp-for="#User.Identity.Name" class="form-control" readonly />
...
In this situation, it really makes no sense to expect #User.Identity.Name in the view to bind to UserName in the view model.
It would seem that the code the IDE generated is wrong. Maybe a messed up scaffolding template somewhere, who knows.
You need to change your asp-for to equal UserName. See below.
<input asp-for="UserName" class="form-control" readonly />
Glad this helped!
Currently I am using following code for email validation but
it does validate the dsgf#g mail id please help me
[Required(ErrorMessage = "Please Enter Email Id")]
[Display(Name = "Email-Id")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Cust_Email { get; set; }
EmailAddress attribute will mark as valid the dsgf#g because it is a completely valid email address, so there is nothing wrong with that method. Consider the example username#localhost for example.
If it is not suits you then you can use regular expression ti set your own rule for validation. Try to use 'RegularExpression' attribute instead, something like:
[RegularExpression("^[^#\s]+#[^#\s]+(\.[^#\s]+)+$", ErrorMessage = "Invalid Email Address")]
public string Cust_Email { get; set; }
or
[RegularExpression(#"^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Invalid Email Address")]
public string Cust_Email { get; set; }
the email is completely valid.
if you want to validate, simply don't use regex for validation. Send him a code to this email-address that he has to enter. email-addresses can now contain characters like ä,ö,ü,à,... this could be really difficult to match the correct one..
if you really want to validate it using regex you could take the RFC822 standard then:
you will find here: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html (have fun with this - didn't want to post, it's too long)
What about an extension method.
public static bool IsValidEmail(this string email)
{
bool rt = false;
try
{
var mail = new System.Net.Mail.MailAddress(email);
rt = mail.Host.Contains(".");
}
catch { }
return rt;
}
Today i'm trying to follow this article of Shai Raiten's Blog and when I finish it the createStatus return invalidAnswer
here is my Register action
[HttpPost]
[AllowAnonymous]
[CaptchaValidation("CaptchaCode", "registerCaptcha", "Wrong captcha!")]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, false, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
MailHelper.SendConfirmationEmail(model.UserName);
return RedirectToAction("Confirmation", "User");
}
else
{
ModelState.AddModelError("", "Failed!");
}
}
return View(model);
}
and here is my RegisterModel.cs
public class RegisterModel
{
[Key]
public long ID { set; get; }
[Required(ErrorMessage = "Do not Skip this")]
public string UserName { set; get; }
[StringLength(500, MinimumLength = 6, ErrorMessage = "Atleast 6 characters in passwords")]
[Required(ErrorMessage = "Do not Skip this")]
public string Password { set; get; }
[Compare("Password", ErrorMessage = "Wrong confirm passwords")]
[Required(ErrorMessage = "Do not skip this")]
public string ConfirmPassword { set; get; }
public string Name { set; get; }
public string Address { set; get; }
[RegularExpression(#"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", ErrorMessage = "This is not an email")]
public string Email { set; get; }
public string Phone { set; get; }
public bool EmailConfirm { set; get; }
}
any suggestion for me , really appreciated all the help you guys make.
The simplest thing you can do is:
First, you should define a property in your user model which will hold email confirmation token. Also, you should define property bool IsEmailConfirmed which defaults to false.
The token should be something like auto-generated random string. E.g. Guid.NewGuid().ToString()
Then, you should define another action, say [HttpGet, AllowAnonymous] ConfirmEmail(string email, string token), which will validate that token against saved in the database and update IsEmailConfirmed accordingly.
And the link you are asking about, should then point to an url which will look like something like that: http://YOUR.SERVER/YourController/ConfirmEmail?email={0}&token={1}, where {0} is user email and {1} is your user email confirmation token. It should return a view that tells whether confirmation was successfull.
However, i do recommend not to reinvent the wheel and to simply use Asp.Net Identity 2.0 framework, which will do all that authn & authz stuff for you.
Please follow the below example from ASP.Net site where its beautifully explained how to send email during registration prcoess.
http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset
Additionally I would not recommend MD5 password hashinh since its pretty old, try using SHA 256 hashing for password encryption.
http://forums.asp.net/t/1211478.aspx?How+do+I+use+Sha256+to+Encrypt+a+String+
The Problem
I have a pre-defined [StringLength()] and [RegularExpression()] constraint on my Code-First Model.
The [StringLength()] requirement is 8-16 characters
The [RegularExpression()] constraint for the password is in a different format from the encrypted password.
The password is encrypted before being shoved into the database.
The encrypted password is 70 characters in length, which is higher than the 8-16 character limit defined in the Model.
I am required to use e.Encrypt(), meaning I cannot use the default ASP.NET hashing algorithm.
I've searched high and low, but have yet to find the correct answer.
My Code
I have a function that allows a user to register an account. It looks like this:
[HttpPost]
public ActionResult Register([Bind(Include="Username,Password,EmailAddress")] UserModel user)
{
if (TryUpdateModel(user))
{
// Set password to a different format than Model's designated Regex
user.Password = e.Encrypt(user.Password);
context.Entry(user).State = EntityState.Added;
context.SaveChanges();
return RedirectToAction("Login", "Account");
}
return View();
}
In my UserModel.cs file, I have the following constraints:
[Required]
[DataType(DataType.Password)]
[StringLength(16, MinimumLength = 8, ErrorMessage = "Must be between 8 and 16 characters.")]
[RegularExpression("^(?=.*[0-9])(?=.*[!##$%^&*])[a-zA-Z0-9!##$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
public string Password { get; set; }
Again, the hashed password is in a completely different format. Therefore, I cannot update it because it throws a DbEntityValidationException. This [RegularExpression()] is for the format of the user's password. I need to be able to bypass or suspend the password's Regex constraint.
What I have done to remedy this
I've removed the [RegularExpression()] requirements, and upped the [StringLength()] to 70, which is the length of my password hash.
However, I don't want to allow users to input 70 characters of text. This seems like a cheap hack, and I feel that there should be a better way to do this. Any ideas?
Here's an example:
We've got different requirements for user input than what our database requires. We might need more user input which we will programmatically act upon.
The EF model
public class UserModel()
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
[Required, StringLength(70)]
public string Password { get; set; }
}
Now here's the class we use to capture user input
public class UserViewModel()
{
[Required]
public string Name { get; set; }
[Required]
[RegularExpression("^(?=.*[0-9])(?=.*[!##$%^&*])[a-zA-Z0-9!##$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
public string Password { get; set; }
[Required]
public string ConfirmPassword { get; set; }
}
Now we transform and map values.
The user won't know what to use for Id and the database doesn't have need for ConfirmPassword. We can also transform what the user originally entered as a password.
[HttpPost]
public ActionResult Register(UserViewModel model)
{
if ((ModelState.IsValid) &&
(model.Password == model.ConfirmPassword))
{
// map to EF model
var user = new UserModel
{
Name = model.Name,
Password = e.encrypt(model.Password) // transform, encrypt, whatever
};
db.Users.Add(user); // use EF model to persist
...
return RedirectToAction("Login", "Account");
}
return(model);
}