Dynamically apply validation rules at runtime with ASP.NET MVC 4

前端 未结 4 1753
遇见更好的自我
遇见更好的自我 2020-12-14 13:02

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

4条回答
  •  有刺的猬
    2020-12-14 13:05

    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.

提交回复
热议问题