1

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).

mituw16
  • 5,126
  • 3
  • 23
  • 48
  • Hope this helps: [RequiredAttribute with AllowEmptyString=true in ASP.NET MVC 3 unobtrusive validation][1] or may be this: [How to convert TextBoxes with null values to empty strings][2] [1]: http://stackoverflow.com/questions/6437150/requiredattribute-with-allowemptystring-true-in-asp-net-mvc-3-unobtrusive-valida [2]: http://stackoverflow.com/questions/3475273/how-to-set-default-value-of-textbox-empty-string-instead-of-null – Ehsan Sajjad Apr 07 '14 at 15:11
  • Unfortunately it doesn't, as I've already tried both of those solutions to no avail :( – mituw16 Apr 07 '14 at 16:05
  • This is why you should always use ViewModel's, rather than directly using your EF models in your view. ViewModels are designed to meet the views needs, not the data models needs. – Erik Funkenbusch Apr 07 '14 at 18:28
  • I thought about that solution, but was being lazy with code first and just decided to use my db context in my view models, instead of typing another class that would look exactly like my ef context model. Using the fluent api worked well with configuring the database, but still allowing me to have my context classes work with my code requirements – mituw16 Apr 07 '14 at 18:32

1 Answers1

1

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);


    }

}
mituw16
  • 5,126
  • 3
  • 23
  • 48