#c# #model-view-controller #class #client-side-validation #attributeusage
#c# #модель-представление-контроллер #класс #проверка на стороне клиента #attributeusage
Вопрос:
Возможно ли реализовать проверку на клиентском сайте для пользовательского атрибута ValidationAttribute, который используется в области видимости класса? Например, мой MaxLengthGlobal, который должен обеспечивать глобальный максимальный предел для всех полей ввода.
[AttributeUsage(AttributeTargets.Class)]
public class MaxLengthGlobalAttribute : ValidationAttribute, IClientValidatable
{
public int MaximumLength
{
get;
private set;
}
public MaxLengthGlobalAttribute(int maximumLength)
{
this.MaximumLength = maximumLength;
}
public override bool IsValid(object value)
{
var properties = TypeDescriptor.GetProperties(value);
foreach (PropertyDescriptor property in properties)
{
var stringValue = property.GetValue(value) as string;
if (stringValue != null amp;amp; (stringValue.Length > this.MaximumLength))
{
return false;
}
}
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = this.FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "maxlengthglobal",
};
rule.ValidationParameters.Add("maxlength", this.MaximumLength);
yield return rule;
}
}
Спасибо.
Ответ №1:
Я нашел этот ответ, когда искал решение той же проблемы, и придумал обходной путь.
Вместо 1 атрибута ValidationAttribute имейте 2:
1.) Атрибут ServerValidationAttribute будет находиться в классе и не будет реализовывать IClientValidatable.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class MyCustomServerValidationAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// remember to cast to the class type, not property type
// ... return true or false
}
}
2.) Атрибут ClientValidationAttribute будет находиться в поле / свойстве и будет реализовывать IClientValidatable, но переопределение isValid всегда возвращает true .
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property,
AllowMultiple = false, Inherited = true)]
public class MyCustomClientValidationAttribute : ValidationAttribute,
IClientValidatable
{
public override bool IsValid(object value)
{
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "mycustomvalidator",
};
var viewContext = (ViewContext)context;
var dependentProperty1 = viewContext.ViewData.TemplateInfo
.GetFullHtmlFieldId("DependentProperty1");
//var prefix = viewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
rule.ValidationParameters.Add("dependentproperty1", dependentProperty1);
yield return rule;
}
}
При выполнении на клиенте атрибут сервера игнорируется, и наоборот.
Если вам нужно иметь атрибут проверки в классе, скорее всего, проверка выполняется для нескольких полей. Я вставил некоторый шаблонный код для передачи дополнительных параметров в метод проверки клиента, но он работает не так, как я ожидал. В моем фактическом коде я закомментировал переменные viewContext и dependentProperty1 и просто передал строку «DependentProperty1» второму аргументу правила.Параметры проверки.Добавить метод. По какой-то причине я получаю неправильное HtmlFieldPrefix . Если кто-нибудь может помочь с этим, пожалуйста, прокомментируйте…
В любом случае, в итоге вы получаете viewmodel, подобный этому:
[MyCustomServerValidation(ErrorMessage = MyCustomValidationMessage)]
public class MyCustomViewModel
{
private const string MyCustomValidationMessage = "user error!";
[Display(Name = "Email Address")]
[MyCustomClientValidation(ErrorMessage = MyCustomValidationMessage)]
public string Value { get; set; }
[HiddenInput(DisplayValue = false)]
public string DependentProperty1 { get; set; }
}
Клиентский скрипт, подобный этому:
/// <reference path="jquery-1.6.2.js" />
/// <reference path="jquery.validate.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
$.validator.addMethod('mycustomvalidator', function (value, element, parameters) {
var dependentProperty1 = $('#' parameters['dependentproperty1']).val();
// return true or false
});
$.validator.unobtrusive.adapters.add('mycustomvalidator', ['dependentproperty1'],
function (options) {
options.rules['mycustomvalidator'] = {
dependentproperty1: options.params['dependentproperty1']
};
options.messages['mycustomvalidator'] = options.message;
}
);
И представление, подобное этому:
@Html.EditorFor(m => m.Value)
@Html.EditorFor(m => m.DependentProperty1)
@Html.ValidationMessageFor(m => m.Value)
@Html.ValidationMessageFor(m => m)
Затем, если у вас отключена проверка клиента, @Html.ValidationMessageFor(m => m)
отображается вместо значения для свойства.
Ответ №2:
Нет, это невозможно. Извините.