I’m trying to understand how model validation works as I finalize the design on my website using ASP.NET Core 8 MVC in Visual Studio. I’ve read several tutorials and posts on here, but the behavior I’m seeing doesn’t seem to match what I was expecting.
using System.ComponentModel.DataAnnotations;
namespace mywebsite.Models
{
public class TestAModel
{
//[Required]
//public int nonnullableint { get; set; }
//public int? nullableint { get; set; }
//public string? nullablestring { get; set; }
//public string nonnullablestring { get; set; }
//public TestCModel? nullablenonrequiredmodel { get; set; }
public TestCModel nonnullablenonrequiredmodel { get; set; }
//public TestBModel? nullablerequiredmodel { get; set; }
//public TestBModel nonnullablerequiredmodel { get; set; }
//public List<TestBModel>? nullablerequiredmodellist { get; set; }
//public List<TestBModel> nonnullablerequiredmodellist { get; set; }
//public List<TestCModel>? nullablenonrequiredmodellist { get; set; }
//public List<TestCModel> nonnullablenonrequiredmodellist { get; set; }
}
}
namespace mywebsite.Models
{
public class TestCModel
{
public int? notrequiredint { get; set; }
}
}
HomeController
‘s Index()
action method:
public IActionResult Index()
{
TestAModel model = new TestAModel();
//model.nonnullablenonrequiredmodel = new TestCModel();
var validate = TryValidateModel(model);
if (ModelState.IsValid)
{
var variabletest = 1;
}
return View(); // breakpoint here to view results
}
What I’ve found, using TestCModel
as an example, basically is this:
public class TestAModel
{
//[Required]
public TestCModel? nonnullablenonrequiredmodel { get; set; }
}
public IActionResult Index()
{
TestAModel model = new TestAModel();
//model.nonnullablenonrequiredmodel = new TestCModel();
var validate = TryValidateModel(model);
if (ModelState.IsValid)
{
var variabletest = 1;
}
return View();
}
This results in validation = true
.
public class TestAModel
{
[Required]
public TestCModel? nonnullablenonrequiredmodel { get; set; }
}
public IActionResult Index()
{
TestAModel model = new TestAModel();
//model.nonnullablenonrequiredmodel = new TestCModel();
var validate = TryValidateModel(model);
if (ModelState.IsValid)
{
var variabletest = 1;
}
return View();
}
This results in validation = false
.
public class TestAModel
{
[Required]
public TestCModel? nonnullablenonrequiredmodel { get; set; }
}
public IActionResult Index()
{
TestAModel model = new TestAModel();
model.nonnullablenonrequiredmodel = new TestCModel();
var validate = TryValidateModel(model);
if (ModelState.IsValid)
{
var variabletest = 1;
}
return View();
}
This again results in validation = true
.
All of which makes sense to me, except then when I did this:
public class TestAModel
{
//[Required]
public TestCModel nonnullablenonrequiredmodel { get; set; }
}
public IActionResult Index()
{
TestAModel model = new TestAModel();
//model.nonnullablenonrequiredmodel = new TestCModel();
var validate = TryValidateModel(model);
if (ModelState.IsValid)
{
var variabletest = 1;
}
return View();
}
I got validation = false
!
I don’t understand this because aren’t classes inherently nullable? I also don’t understand this, because it seems to limit the value of the [Required]
tag. What’s the point of it if something is required simply by leaving it non-nullable? I had the same results with string types as well.
The only thing interesting was int types, because the non-nullable int defaulted to a value = 0, so the way to make it required was [Required]
and nullable.
Am I missing something super basic? Please help.