side - validate model c#
validaciĆ³n del lado del cliente en el atributo de validaciĆ³n personalizada-asp.net mvc 4 (2)
Eche un vistazo a esto: http://thewayofcode.wordpress.com/tag/custom-unobtrusive-validation/
Usando este tutorial, obtuve mi código de validación personalizado ejecutándose sin problemas. La única diferencia que puedo detectar en tu código es la forma en que creaste la función $.validator.unobtrusive.adapters.add
. Los parámetros son un poco diferentes, pero quizás el problema es que no ha definido la parte de la rule
de su adaptador.
Intenta usar algo como esto:
$.validator.unobtrusive.adapters.add("requiredif", ["requiredif"], function (options) {
options.rules["requiredif"] = "#" + options.params.requiredif;
options.messages["requiredif"] = options.message;
});
o esto
$.validator.unobtrusive.adapters.add("requiredif", function (options) {
options.rules["requiredif"] = "#" + options.element.name.replace(''.'', ''_''); // mvc html helpers
options.messages["requiredif"] = options.message;
});
Acerca de la rule
(tomada del enlace):
La matriz de reglas jQuery para este elemento HTML. Se espera que el adaptador agregue elementos a este conjunto de reglas para los validadores jQuery Validate específicos que quiera adjuntar. El nombre es el nombre de la regla jQuery Validate, y el valor son los valores de los parámetros para la regla jQuery Validate.
He seguido algunos artículos y tutoriales en Internet para crear un atributo de validación personalizado que también sea compatible con la validación del lado del cliente en un sitio web asp.net mvc 4. Esto es lo que tengo hasta ahora:
RequiredIfAttribute.cs
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] //Added
public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
private readonly string condition;
private string propertyName; //Added
public RequiredIfAttribute(string condition)
{
this.condition = condition;
this.propertyName = propertyName; //Added
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
PropertyInfo propertyInfo = validationContext.ObjectType.GetProperty(this.propertyName); //Added
Delegate conditionFunction = CreateExpression(validationContext.ObjectType, _condition);
bool conditionMet = (bool)conditionFunction.DynamicInvoke(validationContext.ObjectInstance);
if (conditionMet)
{
if (value == null)
{
return new ValidationResult(FormatErrorMessage(null));
}
}
return ValidationResult.Success;
}
private Delegate CreateExpression(Type objectType, string expression)
{
LambdaExpression lambdaExpression = System.Linq.Dynamic.DynamicExpression.ParseLambda(objectType, typeof(bool), expression); //Added
Delegate function = lambdaExpression.Compile();
return function;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var modelClientValidationRule = new ModelClientValidationRule
{
ValidationType = "requiredif",
ErrorMessage = ErrorMessage //Added
};
modelClientValidationRule.ValidationParameters.Add("param", this.propertyName); //Added
return new List<ModelClientValidationRule> { modelClientValidationRule };
}
}
Luego apliqué este atributo en una propiedad de una clase como esta
[RequiredIf("InAppPurchase == true", "InAppPurchase", ErrorMessage = "Please enter an in app purchase promotional price")] //Added "InAppPurchase"
public string InAppPurchasePromotionalPrice { get; set; }
public bool InAppPurchase { get; set; }
Entonces, lo que quiero hacer es mostrar un mensaje de error indicando que se requiere el campo InAppPurchasePromotionalPrice cuando el campo InAppPurchase es verdadero (eso significa que se marcó en el formulario). El siguiente es el código relevante de la vista:
<div class="control-group">
<label class="control-label" for="InAppPurchase">Does your app include In App Purchase?</label>
<div class="controls">
@Html.CheckBoxFor(o => o.InAppPurchase)
@Html.LabelFor(o => o.InAppPurchase, "Yes")
</div>
</div>
<div class="control-group" id="InAppPurchasePromotionalPriceDiv" @(Model.InAppPurchase == true ? Html.Raw("style=''display: block;''") : Html.Raw("style=''display: none;''"))>
<label class="control-label" for="InAppPurchasePromotionalPrice">App Friday Promotional Price for In App Purchase: </label>
<div class="controls">
@Html.TextBoxFor(o => o.InAppPurchasePromotionalPrice, new { title = "This should be at the lowest price tier of free or $.99, just for your App Friday date." })
<span class="help-inline">
@Html.ValidationMessageFor(o => o.InAppPurchasePromotionalPrice)
</span>
</div>
</div>
Este código funciona perfectamente, pero cuando presento el formulario, se solicita una publicación completa en el servidor para mostrar el mensaje. Así que creé el código JavaScript para habilitar la validación del lado del cliente:
requiredif.js
(function ($) {
$.validator.addMethod(''requiredif'', function (value, element, params) {
/*var inAppPurchase = $(''#InAppPurchase'').is('':checked'');
if (inAppPurchase) {
return true;
}
return false;*/
var isChecked = $(param).is('':checked'');
if (isChecked) {
return false;
}
return true;
}, '''');
$.validator.unobtrusive.adapters.add(''requiredif'', [''param''], function (options) {
options.rules["requiredif"] = ''#'' + options.params.param;
options.messages[''requiredif''] = options.message;
});
})(jQuery);
Esta es la forma propuesta en msdn y tutoriales que he encontrado
Por supuesto, también he insertado los scripts necesarios en el formulario:
- jquery.unobtrusive-ajax.min.js
- jquery.validate.min.js
- jquery.validate.unobtrusive.min.js
- requiredif.js
PERO ... la validación del lado del cliente todavía no funciona. Entonces, ¿podrías ayudarme a encontrar lo que me estoy perdiendo? Gracias por adelantado.
Vale la pena señalar que el atributo [RequiredIf]
debe agregarse al segundo campo de formulario en el modelo de vista para que la validación del cliente funcione.