I'm experiencing the issue while displaying errors in my view for child element. I've got 2 entities Restaurant and Menu with their respective relationships described as below:
public class Restaurant
{
public int ID { get; set; }
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Foundation Date")]
public DateTime FoundationDate { get; set; }
[Required]
public string Country { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Restaurant Name")]
public string RestaurantName { get; set; }
[Required]
[StringLength(100)]
public string Address { get; set; }
public ICollection<Menu> Menus { get; set; }
}
public class Menu
{
public int MenuId { get; set; }
[Required]
[StringLength(20, MinimumLength=2)]
public string Name { get; set; }
[StringLength(50)]
public string Description { get; set; }
public int RestaurantId { get; set; }
public Restaurant Restaurant { get; set; }
public ICollection<Product> Products { get; set; }
}
The issue is happening when I press the create button validations for menu (child entity) are not being displayed at all. I want to be able to capture validations next to my input fields after I submit the form.
Here is my div element which is nested inside a form for triggering create action on my controller.
<div id="menuFields" class="toggable-div" style="display: @ViewData["Visibility"]" data-count="0">
@if (Model?.Menus != null)
{
@foreach (var (menu,i) in Model.Menus.Select((menu, index) => (menu,index)).ToArray())
{
<div class="form-group">
<label asp-for="Menus[@i].Name">Menu Name</label>
<input asp-for="Menus[@i].Name" type="text" class="form-control" id="menuName1" name="Menus[@i].Name" value="@menu.Name" />
<span asp-validation-for="Menus[@i].Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Menus[@i].Description">Menu Description</label>
<input asp-for="Menus[@i].Description" type="text" class="form-control" id="menuDescription@(i)" name="Menus[@i].Description" value="@menu.Description"/>
<span asp-validation-for="Menus[@i].Description" class="text-danger"></span>
</div>
}
}
</div>
I think the issue is validation framework is unable to understand where the Menus is coming from. You should explicitly specify the @Model while accessing Menus and that should resolve the issue.
So, in the CSHTML file, you can use @model.Menus[i] syntax. This will ensure that the validation framework understands that the Menus is nested and it should apply the nested validations.
And my personal preference is to use List<Menu>
instead of ICollection<Menu>
in Restaurant
model. This is to ensure you get some more ways to access the collection.
<div id="menuFields" class="toggable-div" style="display: @ViewData["Visibility"]" data-count="0">
@if (Model?.Menus != null)
{
@foreach (var (menu,i) in Model.Menus.Select((menu, index) => (menu,index)).ToArray())
{
<div class="form-group">
<label asp-for="@Model.Menus[i].Name">Menu Name</label>
<input asp-for="@Model.Menus[i].Name" type="text" class="form-control" id="menuName1" name="@Model.Menus[i].Name" value="@menu.Name" />
<span asp-validation-for="@Model.Menus[i].Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.Menus[i].Description">Menu Description</label>
<input asp-for="@Model.Menus[i].Description" type="text" class="form-control" id="menuDescription@(i)" name="@Model.Menus[i].Description" value="@menu.Description"/>
<span asp-validation-for="@Model.Menus[i].Description" class="text-danger"></span>
</div>
}
}
</div>
Hope this helps !