MVC4 Entity Framework 6 Model State Validation Issues - entity-framework

I'm working on an MVC4 with EF6 project, and have run into a slightly small but frustrating problem. I have a situation where I have the [Required] attribute set in my dbcontext, however, I do want to allow said property to be okay with empty strings.
I have tried what was suggested in this article, http://www.dzone.com/articles/ef-code-firstmvc, as well as putting [DisplayFormat(ConvertEmptyStringToNull = false)] on my context properties.
When I POST from my login page, the First Name, Last Name, Email, Phone properties are null, which is throwing the ModelState out of whack, even though I've set it to allow those properties to be empty strings. Am I missing something?
Model / DBContext
public class User : Entity
{
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String UserName { get; set; }
[StringLength(250)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Password { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String FirstName { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String LastName { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Email { get; set; }
[StringLength(200)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
[Required]
public String Phone { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(UserViewModel Model)
{
var _UM = Model.User;
var User = _repo.GetSingle<User>(x => x.UserName == _UM.UserName);
if(User != null)
{
if (Hash.ValidatePassword(_UM.Password, User.Password))
{
return RedirectToAction("Dashboard");
}
else
{
ModelState.AddModelError("InvalidPass", "Invalid Credentials");
}
}
else
{
ModelState.AddModelError("NoUser", "Invalid Credentials");
}
return View(Model);
}
If invalid credentials are set, I would expect the ModelState keys to only have one of the items that I am explicity setting. However, it has 6 keys (First Name, Last Name, etc are required).

I ended up solving this by moving my EF context configurations to use the Fluent API instead of Data Annotations.
Model / DBContext
public class User : Entity
{
public String UserName { get; set; }
public String Password { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Phone { get; set; }
}
DBContext File
public class DBContext : DbContext
{
public DBContext()
: base("ConString")
{
}
public DbSet<User> Users { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<Region> Regions { get; set; }
public DbSet<InboundFile> InboundFiles { get; set; }
public DbSet<FileType> FileTypes { get; set; }
//configure objects
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(x => x.FirstName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.LastName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Phone).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Email).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.UserName).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(x => x.Password).IsRequired().HasMaxLength(200);
}
}

Related

EFCore Generic Repository and UnitOfWork Design Pattern

when im trying to create new data and save it, im getting error at the
public int Complete()
{
return _context.SaveChanges();
}
and error is saying me that:
The value of 'Agency.ID' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known. .
i have a Base class like that:
public class Base
{
protected Base()
{
CreatedDate = DateTime.Now;
IsDeleted = false;
ModifiedDate = null;
}
public int ID { get; set; }
public int? CreatedUserId { get; set; }
public int? ModifiedUserId { get; set; }
public string CreatedUserType { get; set; }
public string ModifiedUserType { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? ModifiedDate { get; set; }
public bool? IsActive { get; set; }
public bool? IsDeleted { get; set; }
}
i have a Agency class like that :
public class Agency : Base
{
public Agency()
{
AgencyIsComplated = false;
}
[Required, StringLength(255)]
public string AgencyName { get; set; }
[Required, StringLength(255)]
public string AgencyPhoto { get; set; }
[Required, StringLength(255)]
public string AgencyEMail { get; set; }
[Required, StringLength(13)]
public string AgencyPhone { get; set; }
[StringLength(13)]
public string AgencyBPhone { get; set; }
[StringLength(255)]
public string AgencyInfo { get; set; }
[Required, StringLength(255)]
public string AgencyTitle { get; set; }
[Required, StringLength(255)]
public string AgencyLink { get; set; }
public int AgencyExportArea { get; set; } // Join table ile yapılacak,ayrı bir tabloda tutulacak
[Required, StringLength(255)]
public string AgencyInstagram { get; set; }
public string AgencyTwitter { get; set; }
public string AgencyFacebook { get; set; }
public string AgencyLinkedin { get; set; }
public string AgencyYoutube { get; set; }
public bool AgencyIsComplated { get; set; }
[ForeignKey("CompanyID")]
public Company Company { get; set; }
[ForeignKey("LogID")]
public Log Log { get; set; }
public virtual ICollection<AgencyCompany> AgencyCompanies { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<Log> Logs { get; set; }
}
public class AgencyConfiguration : IEntityTypeConfiguration<Agency>
{
public void Configure(EntityTypeBuilder<Agency> builder)
{
builder.HasKey(agency => agency.ID);
builder.HasMany(a => a.Logs)
.WithOne(a => a.Agency)
.HasForeignKey(a=>a.ID)
.OnDelete(DeleteBehavior.Restrict);
builder.HasMany(us => us.Users)
.WithOne(us => us.Agency)
.HasForeignKey(au=>au.ID)
.OnDelete(DeleteBehavior.Restrict);
builder.HasMany(ac => ac.AgencyCompanies)
.WithOne(ac => ac.Agency)
.OnDelete(DeleteBehavior.Restrict);
}
}
and i have got a UnitOfWork like that:
public class UnitOfWork : IUnitOfWork
{
private TradeTurkDBContext _context;
public UnitOfWork(TradeTurkDBContext context)
{
_context = context;
RepositoryAgency = new RepositoryAgency(_context);
}
public IRepository Repository { get; private set; }
public IRepositoryAgency RepositoryAgency { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
im inheriting that ID on my Base Model.
the problem is getting solved when im not defining ID in the base model but i allready set up my mapping on it.
so how can i solve that error without using AgencyID in the Agency model ?
The foreign key is in the details (or child) table. Therefore, e.g. a user, should have an AgencyId as foreign key.
builder.Entity<User>()
.HasOne(u => u.Agency)
.WithMany(a => a.Users)
.HasForeignKey(u => u.AgencyId)
.OnDelete(DeleteBehavior.Restrict);
This key automatically points to the primary key of the master (or parent) table.
User.ID is a primary key. User.AgencyId is a foreign key which (automatically) relates to the primary key Agency.ID.
E.g. see: Configure One-to-Many Relationships using Fluent API in Entity Framework Core

Object reference not set to an instance of an object. Adding User Entity Framework

The thing is I am new in Entity Framework and I must be missing something small.
Anyways, I have three tables and I am getting the error adding the user:
Users
Logins
ShippingProfiles
Relationship:
1 to 1 : Users - logins
1 to many: Users - ShippingProfiles
My code behind:
User user = new User();
user.AddUser(user, firstNameInput.Text, lastNameInput.Text, emailList, bdayInput.Text, emailInput.Text);
My context:
public class DBCS : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<ShippingProfile> ShippingProfiles { get; set; }
public DbSet<Login> Logins { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasRequired(user => user.ShippingProfiles)
.WithRequiredPrincipal();
}
}
So I am trying to add the user and I am getting the error
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Nullable<int> EmailList { get; set; }
public System.DateTime Birthday { get; set; }
public virtual Login Login { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ShippingProfile> ShippingProfiles { get; set; }
public void AddUser(User user,string firstNameInput, string lastNameInput, int emailListInput, string bdayInput, string emailInput)
{
using (var dbContext = new DBCS())
{
user.Birthday = Convert.ToDateTime(bdayInput);
user.Email = emailInput;
user.EmailList = Convert.ToInt32(emailListInput);
user.FirstName = firstNameInput;
user.LastName = lastNameInput;
dbContext.Users.Add(user); // Error Here
dbContext.SaveChanges();
}
}
This can be a stupid question, but I would appreciate some help.
Thanks in advance!
Signature of AddUser have 5 parameters. When using this method you are passing 6 parameters.
Object reference error is coming from implementation of AddUser method, where 'user'' is not initialized and added into dbContext.Users.

Why are my entities not being lazy loaded?

I'm using EF 6 and defining my database with Code First.
The following line of code returns a Transaction entity, however the EndorsementInfo navigation property is null. I've checked the database and there is definitely data for the test data. "var trans" does appear to have a valid IQueryable, but navigation property t.EndorsementInfo is null when it shouldn't be.
var trans = unitOfWork.GetRepository<Transaction>().GetAll().Where(t => t.PolicyId == command.PolicyId);
results.Transactions = new List<TransactionListItem>();
foreach (var t in trans)
{
results.Transactions.Add(new TransactionListItem
{
Id = t.Id,
EffDate = t.EffectiveDate,
EffectiveDate = t.EffectiveDate.ToShortDateString(),
TransactionType = t.TransactionType.ToStringValue(),
EndorsementType = t.TransactionType == TransactionType.Endorsement ?
t.EndorsementInfo.EndorsementType.Description : ""
});
}
Transaction Entity:
public class Transaction : EntityBase
{
[Required]
public TransactionType TransactionType { get; set; }
public long PolicyId { get; set; }
public virtual Policy Policy { get; set; }
[Required]
public DateTime EffectiveDate { get; set; }
public DateTime? ExpirationDate { get; set; }
public string Description { get; set; }
public virtual Quote QuoteInfo { get; set; }
public virtual Cancellation CancellationInfo { get; set; }
public virtual NewBusiness NewBusinessInfo { get; set; }
public virtual Endorsement EndorsementInfo { get; set; }
}
Endorsement Entity
public class Endorsement : EntityBase
{
public Transaction Transaction { get; set; }
public long EndorsementTypeId { get; set; }
public virtual EndorsementType EndorsementType { get; set; }
public int EndorsementNum { get; set; }
[MaxLength(500)]
public string EndorsementDesc { get; set; }
public Decimal? Premium { get; set; }
}
Code First Fluent Configurations
public class TransactionConfiguration : EntityTypeConfiguration<Transaction>
{
public TransactionConfiguration()
{
HasOptional(t => t.QuoteInfo).WithRequired(q => q.Transaction);
HasOptional(t => t.NewBusinessInfo).WithRequired(q => q.Transaction);
HasOptional(t => t.EndorsementInfo).WithRequired(q => q.Transaction);
HasOptional(t => t.CancellationInfo).WithRequired(q => q.Transaction);
}
}
Repositories implementation of GetAll
public IQueryable<T> GetAll(string include)
{
return _set.Include(include);
}
I've checked and rechecked that everything is set up correctly. I don't know what I could be missing.
Thanks.
You are using an opened connection to execute two data readers, you need to enable the multiple result set in the connection string.
MultipleActiveResultSets=True;

How to properly map entities using Fluent API?

I have two entities, a User and a UserProfile. The PK of User is UserId, the PK of UserProfile is UserProfileId. Every time a new user is created in my app, I create a new UserProfile whose PK is the same as the PK in User. When I then try to go update properties on the UserProfile I end up getting multiplicity errors or schema invalid errors. Here are my two entities:
public class User
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? PhoneExtension { get; set; }
public string Comment { get; set; }
public Boolean IsApproved { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public DateTime? LastActivityDate { get; set; }
public DateTime? LastLockoutDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public string ConfirmationToken { get; set; }
public DateTime? CreateDate { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime? LastPasswordChangedDate { get; set; }
public string PasswordVerificationToken { get; set; }
public DateTime? PasswordVerificationTokenExpirationDate { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
public class UserProfile
{
public Guid UserProfileId { get; set; }
public virtual User ProfileOwner { get; set; }
public Int64? HomePhone { get; set; }
public Int64? MobilePhone { get; set; }
public virtual User Manager { get; set; }
}
..and here are my only defined relationships using Fluent API.
modelBuilder.Entity<UserProfile>()
.HasKey(e => e.UserProfileId);
modelBuilder.Entity<UserProfile>()
.Property(e => e.UserProfileId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<UserProfile>()
.HasRequired(e => e.ProfileOwner)
.WithRequiredDependent(r => r.UserProfile);
Finally, my UserService creates a new user and at the same time creates a new UserProfile whose Guid UserProfileId is the same as the User's Guid UserId. Right after the user and profile are created, I try to update the manager in the UserProfile with my UserProfileService using this:
public void UpdateUserProfile(UserProfile updatedUserProfile)
{
UserProfile oldUserProfile = GetUserProfileByID(updatedUserProfile.UserProfileId);
oldUserProfile.Manager = updatedUserProfile.Manager;
oldUserProfile.HomePhone = updatedUserProfile.HomePhone;
oldUserProfile.MobilePhone = updatedUserProfile.MobilePhone;
this.SetEntityState(oldUserProfile, EntityState.Modified);
this.UnitOfWork.SaveChanges();
}
The this.SetEntityState line throws this error:
Multiplicity constraint violated. The role 'UserProfile_ProfileOwner_Source' of the relationship 'WhelenPortal.Data.Context.UserProfile_ProfileOwner' has multiplicity 1 or 0..1.
I've been trying to get this working for TWO DAYS now, PLEASE HELP!!! Thanks in advance.
As requested, here is some additional information. I'm using the repository pattern and unit of work here. My GetUserProfileById code is below. The service uses the repository so I show both.
public UserProfile GetUserProfileByID(Guid id)
{
if (id == null)
throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, new ArgumentNullException("id"));
try
{
Model.UserProfile userProfile = _userProfileRepository.GetUserProfileByID(id);
if (userProfile != null)
return ToServicesUserProfile(userProfile);
return null;
}
catch (InvalidOperationException ex)
{
throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, ex);
}
}
..and the repository:
public UserProfile GetUserProfileByID(Guid id)
{
return this.GetDbSet<UserProfile>().Find(id);
}
So after much playing around this is what ended up working for me, hopefully it can help someone else in some fashion. My User class stayed exactly the same but my UserProfile class changed to this:
public class UserProfile
{
public Guid UserProfileId { get; set; }
public virtual User ProfileOwner { get; set; }
public Guid? ManagerId { get; set; }
public virtual User Manager { get; set; }
public Int64? HomePhone { get; set; }
public Int64? MobilePhone { get; set; }
}
And here is the fluent mapping:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.UserProfile)
.WithRequired(u => u.ProfileOwner);
modelBuilder.Entity<UserProfile>()
.HasOptional(u => u.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerId);
}

How do I map a small object graph using Entity Framework Code First 4.1?

I have a very small object graph that I'm using:
public struct Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
etc...
}
public class User
{
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
public string FirstName { get; set; }
etc...
}
Using Entity Framework 4.1, how would I map this structure to one table so that they're mapped to columns like:
HomeAddressLine1
HomeAddressLine2
WorkAddressLine1
WorkAddressLine2
FirstName
LastName
etc...
EF doesn't support structures. You must use class for your Address and map it as complex type:
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
}
public class User
{
public int Id { get; set; }
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
public string FirstName { get; set; }
}
public class Context : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.HomeAddress.AddressLine1)
.ColumnName("HomeAddressLine1");
// Use the same pattern for all columns of HomeAddress and WorkAddress
}
}