ModelState.IsValid is true if password is empty string - asp.net-mvc

I am passing login model to mvc4 default login method
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _webSecurity.login(model))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
My Model looks like following
var _loginModel = new LoginModel
{
UserName = abc#gmail.com,
Password = ""
};
but ModelState.IsValid is returning true . I don't know why . Help me
Thanks in advance .
Edit
Here is my LoginModel
public class LoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}

The validation Attribute defined in the model will be apllied while Model Binding, u don't have to do this manualy.
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.",MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
For more complex validation you also could add a regex filter like this:
[RegularExpression(#"^[^\<\>]*$", ErrorMessage = "May not contain <,>")]
This would match windows group policy password filter for example:
(?=^.{6,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*

Related

Add Control to validate in ModelState manually

I have one scenario as mentioned below :
In my xyz.cshtml page, i have two form. and in xyz.cshtml.cs page i have one InputModel that contains Property for both form.
public class InputModel
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "Enter a valid email address.")]
[RegularExpression(
#"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)#([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",
ErrorMessage = "Enter a valid email address.")]
public string Email { get; set; }
[Required(ErrorMessage = "The Password field is required.")]
[DataType(DataType.Password)]
public string Password_ChangeEmail { get; set; }
[Required(ErrorMessage = "The OldPassword field is required.")]
[DataType(DataType.Password)]
public string OldPassword { get; set; }
[Required(ErrorMessage = "The New Password field is required.")]
[DataType(DataType.Password)]
[CustomPassword(8, 15, ErrorMessage = "The password is invalid.")]
public string Password { get; set; }
[Required(ErrorMessage = "The Confirm Password field is required.")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "The passwords do not match.")]
public string ConfirmPassword { get; set; }
}
I am using first 2 property in one form and rest of the property in 2nd form.
Now, issue is when i am pressing Submit button from 1st form, it's validating 2nd form as well. So for the time i have used ModelState.Clear() . But if i am using this and i am not wrong it will stop validating all the property.
So, if you guys have any solution like, is it possible to control in ModelState manually for validate.
If i need to share anything else, please suggest.
Thanks
1) You could split the model into two, one model for each form and use them in the post actions for these forms.
public class LoginModel
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "Enter a valid email address.")]
[RegularExpression(
#"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)#([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",
ErrorMessage = "Enter a valid email address.")]
public string Email { get; set; }
[Required(ErrorMessage = "The Password field is required.")]
[DataType(DataType.Password)]
public string Password_ChangeEmail { get; set; }
}
public class ChangePasswordModel
{
[Required(ErrorMessage = "The OldPassword field is required.")]
[DataType(DataType.Password)]
public string OldPassword { get; set; }
[Required(ErrorMessage = "The New Password field is required.")]
[DataType(DataType.Password)]
[CustomPassword(8, 15, ErrorMessage = "The password is invalid.")]
public string Password { get; set; }
[Required(ErrorMessage = "The Confirm Password field is required.")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "The passwords do not match.")]
public string ConfirmPassword { get; set; }
}
2) Create a combined model
public class InputModel
{
public LoginModel LoginModel { get; set; }
public ChangePasswordModel ChangePasswordModel { get; set; }
}
3) add two post actions
public IActionResult LoginPost(InputModel model)
{
...
return View("InputPage", model);
}
public IActionResult ChangePasswordPost(InputModel model)
{
...
return View("InputPage", model);
}
4) use the combined model in your cshtml page
#model InputModel
...
#using (Html.BeginForm("LoginPost", "Home")) {
#Html.TextBoxFor(m => m.LoginModel.Email)
<input type="submit" value="submit" />
}

Exclude property of model in insert Entity Framework

I get an error when inserting data into my database. My database columns are:
username, password
and I added confirmpassword to the model to extend it.
How do I get rid of the confirmpassword to insert the username and password while using the model with confirmpassword property?
My code:
BootstrapTrainingEntities db = new BootstrapTrainingEntities();
var u = new User();
u.username = user.username;
u.password = user.password;
// how to I remove or ignore the confirmPassword property when saving?
db.Users.Add(u);
db.SaveChanges();
Model
[MetadataType(typeof(metadataUser))]
public partial class User
{
public string confirmPassword { get; set; }
}
public class metadataUser
{
[Required(ErrorMessage = "Username is required", AllowEmptyStrings = false)]
[Display(Name ="Username")]
public string username { get; set; }
[Required(ErrorMessage ="Password is required", AllowEmptyStrings = false)]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string password { get; set; }
[Required(ErrorMessage ="Confirmation Password is required", AllowEmptyStrings = false)]
[Display(Name ="Confiramation Password")]
[DataType(DataType.Password)]
[Compare("password",ErrorMessage = "Password does not match")]
public string confirmPassword { get; set; }
}
This SO has three different solutions that may help you:
How not persist property EF4 code first?
Summary:
First try the DataAnnotations approach:
Make sure you include the required library. Then apply the [Not Mapped] annotation to your field in the model.
using System.ComponentModel.DataAnnotations;
[NotMapped]
public string confirmPassword { get; set; }
If this doesn't do it, try to modify your OnModelBuilding method in your dbContext. There are two options in this block. The first is to use the Ignore method.
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MetaDataUser>().Ignore(p => p.confirmPassword);
}
}
The second is to manually remap the model building and exclude your field.
Additional SO answers that may be useful:
Entity Framework Code First - How to ignore a column when saving
Exclude a field/property from the database with Entity Framework 4 & Code-First
MS Doc on how to manually map properties to db fields:
https://learn.microsoft.com/en-us/ef/core/modeling/relational/columns
Clean example of answer provided:
http://www.dotnetodyssey.com/2015/03/31/ignore-class-property-to-table-column-in-entity-framework-code-first/
I think what you need to do is add a viewmodel for the page.First of all you will have model that is generated from entity framework which might look as below.
public class User
{
public int id{get;set;}
public string username {get;set;}
public string password {get;set;}
}
So now create a viewModel for your View .This might look as below.
public class UserViewModel
{
public int id{get;set;}
[Required(ErrorMessage = "Username is required", AllowEmptyStrings = false)]
[Display(Name ="Username")]
public string username { get; set; }
[Required(ErrorMessage ="Password is required", AllowEmptyStrings = false)]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string password { get; set; }
[Required(ErrorMessage ="Confirmation Password is required", AllowEmptyStrings = false)]
[Display(Name ="Confiramation Password")]
[DataType(DataType.Password)]
[Compare("password",ErrorMessage = "Password does not match")]
public string confirmPassword { get; set; }
}
and now in your controller action method. you can do as below.
[HttpPost]
public ActionResult AddUser(UserViewModel model)
{
User user=new User();
user.username=model.username;
user.password=model.password;
db.User.Add(user);
}
Hope it helps !

Insert only that values that are in database field in ASP.NET with EF

I am new To EntityFramework and Also ASP.Net
I am creating an authentication system in Asp.net MVC5 with EF and i have following fields in my db
Id | Name | Contact | Url | Username | Password
and I have my model Clients.cs with a class Clients that need to be stored in database:
public class Clients
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public long? Contact { get; set; }
[Required]
[Display(Name = "Site Url")]
public string Url { get; set; }
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Required]
[Compare("Password", ErrorMessage = "Password Mismatched. Re-enter your password")]
[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
public string ConfirmPassword { get; set; }
}
And I try to store the Credentials as shown below:
//Controller::
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(Clients clients)
{
if (ModelState.IsValid)
{
Clients client = new Clients();
client.Name = clients.Name;
client.Password = clients.Password;
client.Url = clients.Url;
client.Username = clients.Username;
client.Contact = clients.Contact;
dbContext.Clients.Add(client);
dbContext.SaveChanges();
return RedirectToAction("api/products");
}
return View();
}
It shows an error:
Server Error in '/ProductsApp' Application.
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
Source Error:
Line 32:
Line 33: dbContext.Clients.Add(client);
Line 34: dbContext.SaveChanges();
Line 35: return RedirectToAction("Index");
Line 36: }
How do I store all fields in database except ConfirmPassword field.
Use the NotMappedAttribute:
[NotMapped]
public string MyProperty { get; set; }
Your property will become:
[Required]
[Compare("Password", ErrorMessage = "Password Mismatched. Re-enter your password")]
[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
[NotMapped]
public string ConfirmPassword { get; set; }
I solved the problem With the Help of Marthijn
I changed the Clients Confirm Password as:
[Compare("Password", ErrorMessage = "Password Mismatched. Re-enter your password")]
[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
[NotMapped]
public string ConfirmPassword { get; set; }
and Controller's code as:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(Clients clients)
{
if (ModelState.IsValid)
{
dbContext.Clients.Add(client);
dbContext.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
and it worked....
Thanks to Marthijn

How to input data to custom column in userprofile table when creating a new user

I have added a custom column to my user profile table that is called CoID (int).
When I want to create a new user I want to send the value 1 to CoID, but I am experiencing some trouble and cant get it to work properly.
I am using the standard account tables from mvc4.
Here are some of my code
AccountModel.cs
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "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; }
[DataType(DataType.Custom)]
[Display(Name = "CoID")]
[Compare("CoID", ErrorMessage = "plese insert CoID")]
public int CoID { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public int CoID { get; set; }
}
AccountController.cs
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
model.CoID = 1;
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, model.CoID);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
When executing this code i am getting this error:
The custom Data-type string cannot be null or empty.
I think your call to WebSecurity.CreateUserAndAccount might need looking at.
Perhaps the following might work better:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password,
new { CoID = model.CoID });
As from the anonymous object it can work out what values you're trying to assign to what field names. Otherwise you're just passing through the value and it doesn't know where to put it.
Remove [DataType(DataType.Custom)] or change to [DataType("CoID")].

Using custom database in MVC 3 for user login/registration

Okay so I have a MVC project that auto generates an AccountController AcountModel and the associated views.
I created a database with 3 tables using the model first approach, and generated all the controllers/views for all the CRUD operations.
The database contains a user table with a user id, email and password.
How can I use this user table with the auto generated AccountController for user login and registration?
I will show you registration process only , refering which you can build your login/registration with custom database.
Models:
You will add your custommodel to the AccountModels.cs, So it will have following details:
public class ChangePasswordModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Current password")]
public string OldPassword { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[System.Web.Mvc.Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[System.Web.Mvc.Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public class userDetailModel
{
[Key]
public Guid UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string city { get; set; }
public string ConfirmPassword { get; set; }
public string comapny { get; set; }
public int zip { get; set; }
}
Context:
You will add custom context to the Models as below:
public class userDetailsDBContext: DbContext
{
public DbSet<userDetailModel> details { get; set; }
}
Controller:
Now we will modify our AccountController for registration as below:
public class AccountController : Controller
{
private userDetailsDBContext db = new userDetailsDBContext();
// POST: /Account/Register
[HttpPost]
public ActionResult Register(userDetailModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
var newuser = Membership.GetUser(model.UserName);
model.UserId =(Guid)newuser.ProviderUserKey;
db.details.Add(model);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
EDIT web.config:
Finally, you will have to add the new context to the connectionstrings as below:
<connectionStrings>
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MembershipSample-20121105163515;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MembershipSample-20121105163515.mdf" />
<add name="userDetailsDBContext" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MembershipSample-20121105163515;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MembershipSample-20121105163515.mdf" />
</connectionStrings>
You can change the database name to whatever you want and put it as your convenience but put the path here correctly.
Hope you have got the idea now...
I think waht you need is to create custom membership provider. This code project article will give you aplace to start.

Resources