Joe 89
Joe 89

Reputation: 910

ASP.Net MVC 4 Custom Validation attribute isValid is called twice

I am trying to create a sample validation attribute to learn more about MVC. I have created the validation attribute, but when I run the application the validation attribute is called twice -> before calling the controller and before saving the DBContext. I believe this should be called only once. Can you guide me where am I doing wrong.

Validation Attribute: I am trying to validate whether the property has too many words than the specified maxWords

public class ValidationEx : ValidationAttribute
    {
        int _maxWords = 1;
        public ValidationEx()
            : base("{0} has more too many words")
        {
            _maxWords = 1;
        }

        public ValidationEx(int maxWords):base("{0} has more too many words")
        {
            _maxWords = maxWords;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                string data = value as string;
                if (data.Split(' ').Length > _maxWords)
                {
                    var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                    return new ValidationResult(errorMessage);
                }
            }
            return ValidationResult.Success;
        }
    }

Controller:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Album album)
        {
            if (ModelState.IsValid)
            {
                db.Albums.Add(album);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.GenreID = new SelectList(db.Genres, "GenreID", "Name", album.GenreID);
            ViewBag.ArtistID = new SelectList(db.Artists, "ArtistID", "ArtistName", album.ArtistID);
            return View(album);
        }

Note: Validation is fired before reaching controller and while executing db.SaveChanges()

Model:

 public class Album
    {
        public virtual int AlbumID { get; set; }
        public virtual int GenreID { get; set; }
        public virtual int ArtistID { get; set; }

        [Required(ErrorMessageResourceType= typeof(ErrorMessages), ErrorMessageResourceName="TitleRequired")]
        [Display(Name="Movie Name")]
        [ValidationEx()]
        public virtual string Title { get; set; }

        [Range(0,1000)]
        public virtual decimal Price { get; set; }
        public virtual string AlbumArtUrl { get; set; }
        public virtual Genre Genre { get; set; }
        public virtual Artist Artist { get; set; }

        [StringLength(40)]
        public virtual string Description { get; set; }
    }

DBContext

public class MusicAlbumStoreDBContext : DbContext
    {
        // You can add custom code to this file. Changes will not be overwritten.
        // 
        // If you want Entity Framework to drop and regenerate your database
        // automatically whenever you change your model schema, add the following
        // code to the Application_Start method in your Global.asax file.
        // Note: this will destroy and re-create your database with every model change.
        // 
        // System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<MusicAlbumProject.Models.MusicAlbumStoreDBContext>());

        public MusicAlbumStoreDBContext() : base("name=MusicAlbumStoreDBContext")
        {
        }

        public DbSet<Album> Albums { get; set; }

        public DbSet<Genre> Genres { get; set; }

        public DbSet<Artist> Artists { get; set; }

        public DbSet<Order> Orders { get; set; }
    }

Upvotes: 3

Views: 3187

Answers (1)

ViRuSTriNiTy
ViRuSTriNiTy

Reputation: 5155

You are using the same class as model and as view model. There is a reason why MVC distringuishes between these 2 types. You really should add a separate model and a separate view model class.

IsValid() is called twice

  1. before the controller action as the data is validated before the action is called
  2. on db.SaveChanges() because the DB Context also does a validation

Upvotes: 5

Related Questions