I have spent a remarkable amount of time to find out but I couldn't. When I post my model without selecting any option - in fact selecting 0 - Select
- option, the Required
validation is not working.
I also tried removing the programatically added default option from service code to the view code, validation has not worked like this as well.
If I removed the default options completely, then view engine automatically selects the first option from the list and the validation is never be done.
How can I make server side validation done properly?
This is my model
public class AuditViewModel
{
public Guid Id { get; set; }
[Display(Name = "Subject")]
[Required(ErrorMessage = "IsRequired")]
public string Subject { get; set; }
public string AuditType { get; set; }
public string LocationCountry { get; set; }
public string LocationOffice { get; set; }
[Required(ErrorMessage = "IsRequired")]
[Display(Name = "AuditType")]
public int AuditTypeId { get; set; }
public string CreatedOn { get; set; }
public string ModifiedOn { get; set; }
public string CreatedBy { get; set; }
[Display(Name = "Description")]
[Required(ErrorMessage = "IsRequired")]
public string Description { get; set; }
[Display(Name = "Country")]
[Required(ErrorMessage = "IsRequired")]
public int LocationCountryId { get; set; }
[Display(Name = "Office")]
[Required(ErrorMessage = "IsRequired")]
public int LocationOfficeId { get; set; }
[Display(Name = "Season")]
public string Season { get; set; }
public List<SelectListItem> Countries { get; set; }
public List<SelectListItem> AuditTypes { get; set; }
public List<SelectListItem> Offices { get; set; }
public List<AuditViewModel> AuditList { get; set; }
}
This is the service that get select list data and creates the lists for binding
public class AuditViewModelService : IAuditViewModelService
{
public List<SelectListItem> GetAuditTypes()
{
var list = new List<SelectListItem>
{
new SelectListItem { Text = _sharedLocalizer.GetLocalizedString("Select"), Value = "0", Selected = true }
};
foreach (AuditType item in Enum.GetValues(typeof(AuditType)))
{
list.Add(new SelectListItem { Text = _enumLocalizer.GetLocalizedString(item.ToString()), Value = ((int)item).ToString() });
}
return list;
}
public List<SelectListItem> GetCountries()
{
var list = new List<SelectListItem> { new SelectListItem { Text = _sharedLocalizer.GetLocalizedString("Select"), Value = "0", Selected = true } };
list.AddRange(_countryRepository.GetAll().ToList().ToSelectListItemList("Name"));
return list;
}
public List<SelectListItem> GetOffices()
{
var list = new List<SelectListItem> { new SelectListItem { Text = _sharedLocalizer.GetLocalizedString("Select"), Value = "0", Selected = true } };
list.AddRange(_officeRepository.GetAll().ToList().ToSelectListItemList("Name"));
return list;
}
}
An this is select inputs part of the view
<div class="form-group m-form__group">
<label asp-for="AuditTypeId"></label>
<select asp-for="AuditTypeId" asp-items="@Model.AuditTypes" class="form-control m-input m-input--square" id="auditTypeId">
<option value="0">Select</option>
</select>
<span asp-validation-for="AuditTypeId"></span>
</div>
<div class="form-group m-form__group">
<label asp-for="LocationCountryId"></label>
<select asp-for="LocationCountryId" asp-items="@Model.Countries" class="form-control m-input m-input--square" id="locationCountryId">
<option value="0">Select</option>
</select>
<span asp-validation-for="LocationCountryId"></span>
</div>
<div class="form-group m-form__group">
<label asp-for="LocationOfficeId"></label>
<select asp-for="LocationOfficeId" asp-items="@Model.Offices" class="form-control m-input m-input--square" id="locationOfficeId">
<option value="0">Select</option>
</select>
<span asp-validation-for="LocationOfficeId"></span>
</div>
from RequiredAttribute
The RequiredAttribute attribute specifies that when a field on a form is validated, the field must contain a value. A validation exception is raised if the property is null, contains an empty string (""), or contains only white-space characters.
Now look at your model properties
public int LocationCountryId { get; set; }
public int AuditTypeId { get; set; }
public int LocationOfficeId { get; set; }
int
cannot be null, cannot contain an empty string, and cannot take white-space therefore Required
in this context will pass validation every single time. default(int)
will return 0
so you will notice that these properties are 0
on postback.
Either you need to change these to int?
so your property can be in a null state or you need to use the Range
attribute and do something like Range(1, int.MaxValue)
so you can target the 0 value for the error message.