c# - net - validar campos vacios mvc
validaciĆ³n de cliente no intrusiva utilizando fluentvalidation y asp.net mvc LessThanOrEqualTo not disparando (3)
El ejemplo de Darin tiene algunas cosas obsoletas, así que aquí hay un ejemplo más actualizado que tengo que compara números. Sin embargo, puede ajustarlo fácilmente para las comparaciones de fechas:
Javascript:
(function ($)
{
$.validator.addMethod("lessthanorequal", function(value, element, param)
{
return this.optional(element) || parseFloat(value) <= parseFloat(param);
}, "Must be less than");
$.validator.unobtrusive.adapters.add("lessthanorequal", ["field"], function (options)
{
options.rules["lessthanorequal"] = options.params.field;
if (options.message) options.messages["lessthanorequal"] = options.message;
});
})(jQuery);
DO#
public class LessThanOrEqualPropertyValidator : FluentValidationPropertyValidator
{
public LessThanOrEqualPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator)
: base(metadata, controllerContext, rule, validator)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
if (!ShouldGenerateClientSideRules()) yield break;
var formatter = new MessageFormatter().AppendPropertyName(Rule.PropertyName);
string message = formatter.BuildMessage(Validator.ErrorMessageSource.GetString());
var rule = new ModelClientValidationRule
{
ValidationType = "lessthanorequal",
ErrorMessage = message
};
rule.ValidationParameters["field"] = ((LessThanOrEqualValidator)Validator).ValueToCompare;
yield return rule;
}
}
Global.asax Application_Start:
FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(LessThanOrEqualValidator), (metadata, context, description, validator) => new LessThanOrEqualPropertyValidator(metadata, context, description, validator));
});
Entonces, cualquier regla numérica que use LessThanOrEqual será validada por el lado del cliente.
Tengo las siguientes reglas
el primero funciona con una validación no intrusiva del lado del cliente, el segundo no
alguna idea por qué?
RuleFor(x => x.StartDate)
.LessThanOrEqualTo(x => x.EndDate.Value)
.WithLocalizedMessage(() => CommonRes.Less_Than_Or_Equal_To, filters => CommonRes.Start_Date, filters => CommonRes.End_Date);
RuleFor(x => x.StartDate)
.GreaterThanOrEqualTo(x => x.AbsoluteStartDate)
.LessThanOrEqualTo(x => x.AbsoluteEndDate)
.WithLocalizedMessage(() => CommonRes.Between, filters => CommonRes.Start_Date, filters => filters.AbsoluteStartDate, filters => filters.AbsoluteEndDate);
Ninguna de las reglas LessThanOrEqualTo
o GreaterThanOrEqualTo
es respaldada por la validación del lado del cliente como se explica en la documentation .
Esto significa que si quieres tener una validación del lado del cliente para ellos necesitarás escribir un FluentValidationPropertyValidator
personalizado e implementar el método GetClientValidationRules
que te permitirá registrar un adaptador personalizado e implementar la lógica de validación del lado del cliente en javascript.
Si está interesado en cómo se puede lograr esto, solo haga clic en mí y le daré un ejemplo.
Actualizar
Como petición, intentaré mostrar un ejemplo de cómo se podría implementar la validación personalizada del lado del cliente para la regla LessThanOrEqualTo
. Solo es un caso particular con fechas que no admiten nulos. Escribir dicho validador personalizado del lado del cliente para todos los casos posibles es, por supuesto, posible, pero requerirá mucho más esfuerzo.
Entonces comenzamos con un modelo de vista y un validador correspondiente:
[Validator(typeof(MyViewModelValidator))]
public class MyViewModel
{
[Display(Name = "Start date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime StartDate { get; set; }
public DateTime DateToCompareAgainst { get; set; }
}
public class MyViewModelValidator : AbstractValidator<MyViewModel>
{
public MyViewModelValidator()
{
RuleFor(x => x.StartDate)
.LessThanOrEqualTo(x => x.DateToCompareAgainst)
.WithMessage("Invalid start date");
}
}
Entonces un controlador:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
StartDate = DateTime.Now.AddDays(2),
DateToCompareAgainst = DateTime.Now
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
y una vista:
@model MyViewModel
@using (Html.BeginForm())
{
@Html.Hidden("DateToCompareAgainst", Model.DateToCompareAgainst.ToString("yyyy-MM-dd"))
@Html.LabelFor(x => x.StartDate)
@Html.EditorFor(x => x.StartDate)
@Html.ValidationMessageFor(x => x.StartDate)
<button type="submit">OK</button>
}
Todo esto es estándar hasta ahora. Funcionará pero sin la validación del cliente.
El primer paso es escribir FluentValidationPropertyValidator
:
public class LessThanOrEqualToFluentValidationPropertyValidator : FluentValidationPropertyValidator
{
public LessThanOrEqualToFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator)
: base(metadata, controllerContext, rule, validator)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
if (!this.ShouldGenerateClientSideRules())
{
yield break;
}
var validator = Validator as LessThanOrEqualValidator;
var errorMessage = new MessageFormatter()
.AppendPropertyName(this.Rule.GetDisplayName())
.BuildMessage(validator.ErrorMessageSource.GetString());
var rule = new ModelClientValidationRule
{
ErrorMessage = errorMessage,
ValidationType = "lessthanorequaldate"
};
rule.ValidationParameters["other"] = CompareAttribute.FormatPropertyForClientValidation(validator.MemberToCompare.Name);
yield return rule;
}
}
que se registrará en Application_Start
al configurar nuestro proveedor de FluentValidation:
FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(LessThanOrEqualValidator), (metadata, context, rule, validator) => new LessThanOrEqualToFluentValidationPropertyValidator(metadata, context, rule, validator));
});
Y el último bit es el adaptador personalizado en el cliente. Así que agregamos, por supuesto, los 2 scripts a nuestra página para permitir una validación discreta del lado del cliente:
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
y el adaptador personalizado:
(function ($) {
$.validator.unobtrusive.adapters.add(''lessthanorequaldate'', [''other''], function (options) {
var getModelPrefix = function (fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
};
var appendModelPrefix = function (value, prefix) {
if (value.indexOf("*.") === 0) {
value = value.replace("*.", prefix);
}
return value;
}
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];
options.rules[''lessthanorequaldate''] = element;
if (options.message != null) {
options.messages[''lessthanorequaldate''] = options.message;
}
});
$.validator.addMethod(''lessthanorequaldate'', function (value, element, params) {
var parseDate = function (date) {
var m = date.match(/^(/d{4})-(/d{1,2})-(/d{1,2})$/);
return m ? new Date(parseInt(m[1]), parseInt(m[2]) - 1, parseInt(m[3])) : null;
};
var date = parseDate(value);
var dateToCompareAgainst = parseDate($(params).val());
if (isNaN(date.getTime()) || isNaN(dateToCompareAgainst.getTime())) {
return false;
}
return date <= dateToCompareAgainst;
});
})(jQuery);
LessThanOrEqualTo
y GreaterThanOrEqualTo
no son compatibles con la validación de LessThanOrEqualTo
GreaterThanOrEqualTo
momento.
Sin embargo, InclusiveBetween
es compatible. Entonces podrías usar InclusiveBetween
.
Ejemplo
RuleFor(x => x.StartDate)
.InclusiveBetween(x.AbsoluteStartDate, x.AbsoluteEndDate)
Consulte la documentación para obtener más información sobre los documentation .