C# valid ModelState fails .isValid
Search Controller
//
// GET: /Search/Create
public ActionResult Create() { return View(); }
//
// POST: /Search/Create
[HttpPost]
public ActionResult Create(Search search)
{
search.Created = DateTime.Now;
search.SearchSet = "test data";
search.URLParameter = 1432567389;
if (ModelState.IsValid)
{
_db.Searchs.Add(search);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(search);
}
Search Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace TalentProfile.Models
{
public class Search
{
public int Id { get; set; }
[Required]
public int URLParameter { get; set; }
[Required, MaxLength(50, ErrorMessage = "Client must be 50 characters or less")]
public string Client { get; set; }
[DataType(DataType.MultilineText), StringLength(150, ErrorMessage = "{0} must be {1} characters or less")]
public string Notes { get; set; }
[Required]
public string SearchSet { get; set; }
[Required]
public DateTime Created { get; set; }
}
}
If I run in debug all the fields in the class are properly set but it fails ModelState.IsValid. If I drill into the ModelState.IsValid it is false. Drilling down further I find the error “The SearchSet field is required”.
The SearchSet field is properly set to “test data”. If I remove the ModelState.IsValid check the save to the database succeeds.
Why am I getting the “field is required” error if the field contains valid data.
Talent Controller
//
// GET: /Talent/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Talent/Create
[HttpPost]
public ActionResult Create(Talent talent)
{
talent.Modified = talent.Created = DateTime.Now;
if (ModelState.IsValid)
{
_db.Talents.Add(talent);
_db.SaveChanges();
CreatePhoto(talent.Id);
return RedirectToAction("Index");
}
return View(talent);
}
Updated: Search Controller and Create View
//
// GET: /Search/Create
public ActionResult Create()
{
Search search = new Search();
search.SearchSet = "test Data";
return View(search);
}
//
// POST: /Search/Create
[HttpPost]
public ActionResult Create(Search search)
{
search.Created = DateTime.Now;
search.URLParameter = 1435267836;
if (ModelState.IsValid)
{
_db.Searchs.Add(search);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(search);
}
In view put: @Html.HiddenFor(model => model.SearchSet)
There are a couple of things to note here:
1) putting a Required attribute on value types is pointless. Value types must always contain a value, they can’t be null.. thus Required will always pass for them.
In particular, DateTime is a value type. Also, your UrlParameter is an int, which is also a value type. it will always contain at least a default value. Required is redundant.
2) As others have said, the ModelState is only set during databinding. data binding only occurs before the method is called, or when you call UpdateModel or TryUpdateModel. Regardless of whether or not you have other errors, you cannot update the model and expect the ModelState to reflect the changes if you have not called UpdateModel or TryUpdateModel.
3) Client is set as required, but you don’t seem to be setting it. So if you set Client and SearchSet then do TryUpdateModel(search) it should be valid.
4) Talent works because, like in Search,
talent.Modifiedandtalent.CreatedareDateTimes and are non-nullable, thus they will never fail validation, even if you don’t set a value (see for yourself, remove the assignment and see how it still validates). Any other required fields you may have on Talent are likely also value types.