I'm working on a project using MVC3. I've first created a database (with the necessary constraints like PK and FK's) and added this database to my webapplicatie using the ADO.NET Entity Data Model. Everything seems to work fine but I can't make validation flexible. Here some code to clarify my question.
Edit: Added the View + correct models. This version is without importing a database but results the same.
--Models----
namespace CustomValidation.Models
{
public class Person : IValidatableObject
{
public int Id { get; set; }
[Required]
public String FirstName { get; set; }
[Required]
public String LastName { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (String.IsNullOrEmpty(FirstName))
{
var field = new[] { "FirstName" };
yield return new ValidationResult("Firstname can't be null", field);
}
}
}
}
namespace CustomValidation.Models
{
public class Address : IValidatableObject
{
public int Id { get; set; }
[Required]
public String Streetname { get; set; }
[Required]
public String Zipcode { get; set; }
[Required]
public String City { get; set; }
[Required]
public String Country { get; set; }
public Person Person { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (String.IsNullOrEmpty(Streetname))
{
var field = new[] { "Streetname" };
yield return new ValidationResult("Streetname can't be null", field);
}
}
}
}
public class MasterModel
{
public List<Address> Addressess { get; set; }
public Person Person { get; set; }
}
}
namespace CustomValidation.Models
{
public class DBEntities : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Address> Addressess { get; set; }
}
}
----Controller----
namespace CustomValidation.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
MasterModel Model = new MasterModel();
Model.Person = new Person();
Model.Addressess = new List<Address>();
Model.Addressess.Add(new Address());
Model.Addressess.Add(new Address());
return View(Model);
}
[HttpPost]
public ActionResult Index(MasterModel Model)
{
DBEntities _db = new DBEntities();
if (TryValidateModel(Model.Person))
{
_db.People.Add(Model.Person);
_db.SaveChanges();
}
else
{
return View(Model);
}
for (int i = 0; i < Model.Addressess.Count; i++)
{
if (!String.IsNullOrEmpty(Model.Addressess[i].Country))
{
if (TryValidateModel(Model.Addressess[i]))
{
Model.Addressess[i].Person = Model.Person;
_db.Addressess.Add(Model.Addressess[i]);
_db.SaveChanges();
}
else
{
return View(Model);
}
}
}
return RedirectToAction("Index");
}
}
Here is my View:
@model CustomValidation.Models.MasterModel
@{
ViewBag.Title = "Index";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.FirstName)
@Html.EditorFor(m => Model.Person.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.LastName)
@Html.EditorFor(m => Model.Person.LastName)
</div>
</fieldset>
for (int i = 0; i < Model.Addressess.Count; i++)
{
<fieldset>
<legend>Address</legend>
<div class="editor-label">
@Html.LabelFor(model => Model.Addressess[i].Streetname)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Addressess[i].Streetname)
@Html.ValidationMessageFor(model => Model.Addressess[i].Streetname)
</div>
<div class="editor-label">
@Html.LabelFor(model => Model.Addressess[i].Zipcode)
</div>
<div class="editor-field">
@Html.EditorFor(model => Model.Addressess[i].Zipcode)
@Html.ValidationMessageFor(model => Model.Addressess[i].Zipcode)
</div>
<div class="editor-label">
@Html.LabelFor(model => Model.Addressess[i].City)
</div>
<div class="editor-field">
@Html.EditorFor(model => Model.Addressess[i].City)
@Html.ValidationMessageFor(model => Model.Addressess[i].City)
</div>
<div class="editor-label">
@Html.LabelFor(model => Model.Addressess[i].Country)
</div>
<div class="editor-field">
@Html.EditorFor(model => Model.Addressess[i].Country)
@Html.ValidationMessageFor(model => Model.Addressess[i].Country)
</div>
</fieldset>
}
<p>
<input type="submit" value="Create" />
</p>
}
The problem (that I've noticed while debugging something like this) is that before the request gets inside of my action MVC first runs validators for your collection. So if I've only filled out Person in my form, while validating Model.Person it just return false (i guess because of the Required fields for Address) and so it will bounce back to my View.
I need to have some workaround that lets me decided which instances of my collection I want to validate in my action.
I've not been able to find any solution after a lot of time searching on the net.
I hope that someone can help me out.
PS. I'm quite a newbie with Visual Studio and MVC 3 so please don't be to hard on me :)