Given the following classes:
using System.ComponentModel.DataAnnotations;
public class Book{
public Contact PrimaryContact{get; set;}
public Contact SecondaryContact{get; set;}
[Required(ErrorMessage="Book name is required")]
public string Name{get; set;}
}
public class Contact{
[Required(ErrorMessage="Name is required")]
public string Name{get; set;}
}
Is there a clean way I can give a distinct error message for each instance of Contact
in Book
using DataAnnotations
? For example, if the name was missing from the PrimaryContact
instance the error would read "primary contact name is required".
My current solution is to create a validation service that checks the model state for field errors, then remove said errors and add them back using the specific language I'd like.
In Asp.net MVC, we can easily apply validation to web application by using Data Annotation attribute classes to model class. Data Annotation attribute classes are present in System.
DataAnnotations namespace includes the following validator attributes: Range – Enables you to validate whether the value of a property falls between a specified range of values. RegularExpression – Enables you to validate whether the value of a property matches a specified regular expression pattern.
The Validation Error Message property lets you define a custom error message to display if the validation checks specified in the Validation (Regex) fails.
ValidationAttribute, has an important property, ErrorMessage. This property get or set the custom validation message in case of error.
This is the only way I know of that, but it's far from clean. It involves using subclassing and MetaData classes to "override" the error message.
public class Book { public PrimaryContact PrimaryContact { get; set; } public SecondaryContact SecondaryContact { get; set; } [Required(ErrorMessage = "Book name is required")] public string Name { get; set; } } public class Contact { [Required(ErrorMessage = "Name is required")] public string Name { get; set; } } [MetadataType(typeof(PrimaryContactMD))] public class PrimaryContact : Contact { class PrimaryContactMD { [Required(ErrorMessage = "Primary Contact Name is required")] public string Name { get; set; } } } [MetadataType(typeof(SecondaryContactMD))] public class SecondaryContact : Contact { class SecondaryContactMD { [Required(ErrorMessage = "Secondary Contact Name is required")] public string Name { get; set; } } }
You may want to look at using the CustomValidation
attribute for such properties instead of relying on the Required
attribute.
CustomValidation
will allow you to more granularly tailor your validation messages to the property you are validating. I've used context.DisplayName
to dynamically display the name of the property being validated just for brevity, but this can be customized further based on your needs.
If even further customization is needed, you can write different CustomValidation
handlers for each individual property instead of just reusing the same one as I've done in my code example.
using System.ComponentModel.DataAnnotations; public class Book { [CustomValidation(typeof(Book), "ValidateContact")] public Contact PrimaryContact { get; set; } [CustomValidation(typeof(Book), "ValidateContact")] public Contact SecondaryContact { get; set; } [Required(ErrorMessage = "Book name is required")] public string Name { get; set; } public static ValidationResult ValidateContact(Contact contact, ValidationContext context) { ValidationResult result = null; if (contact == null) { result = new ValidationResult($"{context.DisplayName} is required."); } else if (string.IsNullOrWhiteSpace(contact.Name)) { result = new ValidationResult($"{context.DisplayName} name is required."); } return result; } } public class Contact { [Required(ErrorMessage = "Name is required")] public string Name { get; set; } }
The Below code in c# to format data annotations error and format in append format in single string
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
if (actionContext.ModelState.IsValid) return;
string errors = actionContext.ModelState.SelectMany(state => state.Value.Errors).Aggregate("", (current, error) => current + (error.ErrorMessage + ". "));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With