Entity framework code first data annotation not working - asp.net-mvc

Hi I am using entity framework code first approach for my project.
i have a class called Login as shown below
public class Login
{
[Required(ErrorMessage = "UserName Required")]
[DisplayName("Username")]
[Key]
public string Username { get; set; }
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password Required")]
[DisplayName("Password")]
public string Password { get; set; }
[Required(ErrorMessage = "Email Id Required")]
[DisplayName("Email ID")]
[RegularExpression(#"^\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*$",
ErrorMessage = "Email Format is wrong")]
public string Email { get; set; }
}
My database context is as below
public class ContextDB:DbContext
{
public DbSet<Login> LoginModel { get; set; }
}
The table created in the database is Logins.
In my view the validation messages are not working.
Can anyone please help?

This might sound stupid bud are u sure that you are passing right class to your Login ActionResult, not some LoginViewModel or similar stuff? I know that by default some preloaded models exist, so make sure that this isnt case.

Related

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 !

ASP.NET 4 Membeship schema changed

I've installed yesterday Visual Studio 2012 (RTM, via mytt DreamSpark account) and created a demo MVC site (using .NET 4.0 since I wish it to be supported on Azure).
I've started to investigate the project and in addition to built-in option to use external services (Facebook, Twitter, Windows Live and Google) I've found out that the entire membership schema has been changed:
The new structure contains 4 tables (the UserProfile is a first-code approch Entity Framework table).
Note that although the tables prefix is "webpages_" its a proper MVC 4 site.
I've opened the AccountModels.cs file and saw that it has been changed too:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
namespace MyGuestbook.Models
{
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
public class RegisterExternalLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
public string ExternalLoginData { get; set; }
}
public class LocalPasswordModel
{
[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")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
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; }
}
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; }
}
public class ExternalLogin
{
public string Provider { get; set; }
public string ProviderDisplayName { get; set; }
public string ProviderUserId { get; set; }
}
}
So I would like to ask:
- Does this the new users structure (that is generated from asp_regsql.exe) or this is a template-specific structure?
- Does somebody have any documentation about the new structure and how to integrate with it?
- Does anybody know how one can migrate an "older" project (e.g. MVC 3 project) with the old structure to the new one?
Thanks! :)
I've found some article that answer my question.
Edit:
Why the sudden changes:
The changes has been made because Microsoft has changed the default ASP.NET MVC 4 template.
The standard "Internet Application" template which gives default accounts management has been changed and now using the WebMatrix 2 helpers.
The AccountController has been totally rewritten in order to use SimpleMembership class which supports the third-party integration and gives us the ability to use Entity Framework code-first approach.
Usage of old membership providers
As long as I've read, because the SimpleMembership class using ExtendedMembershipProvider you cannot use the default universal providers and must use the built-in provider OR creating an ExtendedMembershipProvider custom provider.
More information can be found here:
Implementing membership providers using the new ASP.NET WebForms and ASP.NET MVC 4 template
Cheers!

Asp.Net MVC 3: Compare validator on subproperties?

For the edition of my user, I've to ensure that password and the repeat password are the same. I found the "Compare" validator, but I cant make it work.
my model looks like the following:
public class UserEditionViewModel{
[Compare("User.Password")]
public String RepeatPassword{get;set;}
public User User {get;set;}
public List<Language> AvailableLanguages{get;set;}
public List<Country> AvailableCountries{get;set;}
}
and the User model:
public class User{
[Required]
public String Name{get;set;}
//lot of other properties omitted...
[RegularExpression(#"(|.*(?=.{6,})(?=.*\d)(?=.*[a-zA-Z]).*)", ErrorMessageResourceType = typeof(LocalizationResources.Views.User.Edition), ErrorMessageResourceName = "InvalidPassword")]
//And I've localization attributes
public String Password{get;set;}
}
In the view I only have something like:
#Html.PasswordFor(m=>m.User.Password)
#Html.PasswordFor(m=>m.RepeatPassword)
But I ever get this error, even if the two items are matching:
'Password repeat' and 'User.Password' do not match.
I also got this error when I'm doing the client validation.
For me the most obvious error is that it can't found the subproperty. Am I right? If yes, how to avoid this behavior. If no, what can be the problem???
A workaround would be to create another property on the UserEditionViewModel that reads and writes to the inner Userclass.
public String UserPassword
{
get
{
return User.Password;
}
set
{
User.Password = value;
}
}
And then bind your controls to that property instead, and change the [Compare("User.Password")] to [Compare("UserPassword")]. I'm not really sure if it can be done any other way short of writing your own custom validator.
I had a similar problem and ended up writing my own validator for this which turned out surprisingly complex since you can have any layer of inheritance to get to your property. If there is another solution, I'd be equally happy to know about it.
You can try this which worked for me..
In your project -> References-> right click->Manage NuGet Packages..
install DataAnnotationsExtensions package.
Then validate your model as follows:
public class Employee
{
[Required(ErrorMessage="Name field Required")]
public string name { get; set; }
[Required(ErrorMessage = "Name field Required")]
public string email { get; set; }
[Required(ErrorMessage = "Depatrment field Required")]
public string department { get; set; }
[Required(ErrorMessage = "Designation field Required")]
public string designation { get; set; }
public string phone { get; set; }
[Required(ErrorMessage = "Password field Required")]
[Display(Name="Password")]
public string password { get; set; }
[Required(ErrorMessage="Confirm password")]
[Display(Name="Re-type Password")]
[EqualToAttribute("password",ErrorMessage="Password miss-match")]
public string Re_Password { get; set; }
}
That's it

How do I set up the validation of a class across 2 screens?

I have a class, employee, in which the user inputs values for the properties on one screen, and then some more on another screen.
The problem I have with this is how to validate these properties?
If I put validation attributes for the properties of the class I have a problem. The validation takes place whether the field is displayed on the form or not.
So for my Employee class I have had to comment out some of the validation in order to get it to work on 1 screen. It probably won't work on the other.
private sealed class Metadata
{
[HiddenInput(DisplayValue=false)]
public int EmployeeId { get; set; }
[DisplayName("Forename")]
[DataType(DataType.Text)]
[Required(ErrorMessage = "Forename is required")]
public string Forename { get; set; }
[DisplayName("Surname")]
[DataType(DataType.Text)]
[Required(ErrorMessage = "Surname is required")]
public string Surname { get; set; }
[DisplayName("Middle Names")]
[DataType(DataType.Text)]
public string Middlenames { get; set; }
//[DisplayName("User Name")]
//[DataType(DataType.Text)]
//[Required(ErrorMessage = "User name is required")]
//public string UserName { get; set; }
[DisplayName("Employee Number")]
[DataType(DataType.Text)]
[Required(ErrorMessage = "EmployeeNumber is required")]
public string EmployeeNumber { get; set; }
[DisplayName("Department")]
[UIHint("DropDownList")]
[Required(ErrorMessage = "You must select a department from a division")]
public int DepartmentId { get; set; }
[DisplayName("User Role")]
[UIHint("DropDownList")]
[Required(ErrorMessage = "You must select a role")]
public int SHP_UserRoleId { get; set; }
//[DisplayName("Email")]
//[DataType(DataType.EmailAddress)]
//[Required(ErrorMessage = "Email is required")]
//[RegularExpression(#"^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$", ErrorMessage = "Not a valid email")]
//[UniqueEmail(ErrorMessage = "User already exists")]
//public string EmailAddress { get; set; }
[DisplayName("End Date")]
public DateTime? EndDate { get; set; }
}
That's a common problem people encounter when they try to use their business models in the views and the reason for this is that business models are closer to the business and the view is closer to the application (it's just a representation of this business model). Today you have two screens, tomorrow maybe three.
For this reason I would recommend you using view models which reflect a given view. So in your case you could have two view models for each view and populate them from the same business model. Validation attributes could be placed on view models. To avoid boilerplate code in converting between your business models and your view models you could use AutoMapper.

asp mvc validation specific to controllers action?

Can the built in ASP MVC validation be made to behave differently for different actions of a same controller ? For example I have a user controller and it has actions like create, edit and other actions. So in model user the attribute Username is being validated for its uniqueness. If there is an user present with the same username, it throws and error username already present. So using the same validator for edit action throws an error "username already present" while editing an user. Can anybody tell me if there is a way to do solve this problem? I am pasting my validator code for reference.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Models
{
[MetadataType(typeof(AdmiUserMetadata))]
public partial class AdminUser
{
public class AdmiUserMetadata
{
[Required(ErrorMessage = "Required Field")]
public string Id { get; set; }
[Required(ErrorMessage = "Required Field")]
[RegularExpression("[\\S]{6,}", ErrorMessage = "Must be at least 6 characters.")]
[Username(ErrorMessage = "Username already taken")]
public string Username { get; set; }
[Required(ErrorMessage = "Required Field")]
[RegularExpression("[\\S]{6,}", ErrorMessage = "Must be at least 6 characters.")]
public string Password { get; set; }
[Required(ErrorMessage = "Required Field")]
public string Name { get; set; }
[Required(ErrorMessage = "Required Field")]
[RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$", ErrorMessage ="Invalid E-mail ID")]
public string Email { get; set; }
[Required(ErrorMessage = "Required Field")]
[RegularExpression("(Active|Disabled)", ErrorMessage = "Select the status of User")]
public string Status { get; set; }
[Required(ErrorMessage = "Required Field")]
[RegularExpression("^[1-9]", ErrorMessage = "Select the group of User")]
public string Group { get; set; }
}
}
public class UsernameAttribute : ValidationAttribute
{
IUserRepository _repository = new UserRepository();
public override bool IsValid(object value)
{
if (value == null)
return true;
if (_repository.IsUsernamePresent((string)value))
{
return false;
}
return true;
}
}
}
What you are validating is a business rule.
No two users can have the same username.
I would have a User service that enforces this rule on creation/edit. Attributes are best suited for input validation. (eg Is the integer non-negative? A valid email address? etc)
I don't see how this can be done if a class has attributes that determines validation. This obviously works for most projects, but for me this is also not working out.
If you need to attach different sets of validation rules check out http://fluentvalidation.codeplex.com/. I tried it and liked it.
It doesn't handle client validation. I dropped that because I have ajax calls in most parts and that feels a bit like client validation.

Resources