I\'ve been working in WebForms for years but I\'m fairly new to .NET\'s flavor of MVC. I am trying to figure out how to apply dynamic validation rules to members of my model
As i said in my comment above i have done something similar using reflection. You can ignore some of it, you probably don't need the dictionary for example, as that was just a way of giving them custom translatable messages.
Server side code:
private static Dictionary _requiredValidationDictionary;
private static Dictionary RequiredValidationDictionary(UserBase model)
{
if (_requiredValidationDictionary != null)
return _requiredValidationDictionary;
_requiredValidationDictionary = new Dictionary
{
{ model.GetPropertyName(m => m.Publication), ErrorMessageToken.PublicationRequired},
{ model.GetPropertyName(m => m.Company), ErrorMessageToken.CompanyRequired},
{ model.GetPropertyName(m => m.JobTitle), ErrorMessageToken.JobTitleRequired},
{ model.GetPropertyName(m => m.KnownAs), ErrorMessageToken.KnownAsRequired},
{ model.GetPropertyName(m => m.TelephoneNumber), ErrorMessageToken.TelephoneNoRequired},
{ model.GetPropertyName(m => m.Address), ErrorMessageToken.AddressRequired},
{ model.GetPropertyName(m => m.PostCode), ErrorMessageToken.PostCodeRequired},
{ model.GetPropertyName(m => m.Country), ErrorMessageToken.CountryRequired}
};
return _requiredValidationDictionary;
}
internal static void SetCustomRequiredFields(List requiredFields, UserBase model, ITranslationEngine translationEngine)
{
if (requiredFields == null || requiredFields.Count <= 0) return;
var tokenDictionary = RequiredValidationDictionary(model);
//Loop through requiredFields and add Display text dependant on which field it is.
foreach (var requiredField in requiredFields.Select(x => x.Trim()))
{
ILocalisationToken token;
if (!tokenDictionary.TryGetValue(requiredField, out token))
token = LocalisationToken.GetFromString(string.Format("{0} required", requiredField));
//add to the model.
model.RequiredFields.Add(new RequiredField
{
FieldName = requiredField,
ValidationMessage = translationEngine.ByToken(token)
});
}
}
internal static void CheckForRequiredField(ModelStateDictionary modelState, T fieldValue, string fieldName, IList requiredFields, Dictionary tokenDictionary)
{
ILocalisationToken token;
if (!tokenDictionary.TryGetValue(fieldName, out token))
token = LocalisationToken.GetFromString(string.Format("{0} required", fieldName));
if (requiredFields.Contains(fieldName) && (Equals(fieldValue, default(T)) || string.IsNullOrEmpty(fieldValue.ToString())))
modelState.AddModelError(fieldName, token.Translate());
}
internal static void CheckForModelErrorForCustomRequiredFields(UserBase model, Paladin3DataAccessLayer client, ICache cache, ModelStateDictionary modelState)
{
var requiredFields = Common.CommaSeparatedStringToList (client.GetSettingValue(Constants.SettingNames.RequiredRegistrationFields, cache: cache, defaultValue: String.Empty, region: null)).Select(x => x.Trim()).ToList();
var tokenDictionary = RequiredValidationDictionary(model);
foreach (var property in typeof(UserBase) .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
CheckForRequiredField(modelState, property.GetValue(model, null), property.Name, requiredFields, tokenDictionary);
}
}
On the model we have a List
which is basically a class with two strings, one for the field name and one for the error message.
Once you have passed the model into the view you need a bit of jQuery to add the validation stuff to the page if you want to do the check server side.
Client side code:
$("#YOURFORM").validate();
for (var x = 0; x < requiredFields.length; x++) {
var $field = $('#' + requiredFields[x].FieldName.trim());
if ($field.length > 0) {
$field.rules("add", {
required: true,
messages: {
required: "" + requiredFields[x].ValidationMessage
//required: "Required Input"
}
});
$field.parent().addClass("formRequired"); //Add a class so that the user knows its a required field before they submit
}
}
Apologies if any of this is not very clear. Feel free to ask any questions and I will do my best to explain.