DataAnnotation с пользовательским ResourceProvider - PullRequest
19 голосов
/ 04 декабря 2009

Я создал custom ResourceProvider для извлечения информации о локализации из базы данных. Теперь я хочу использовать DataAnnotation для добавления проверки к модели.

DataAnnotation имеет свойства ErrorMessageResourceType и ErrorMessageResourceName, но ErrorMessageResourceType принимает только System.Type (то есть скомпилированный файл ресурсов)

Есть ли способ заставить DataAnnotation использовать пользовательский ResourceProvider?

Ответы [ 3 ]

6 голосов
/ 18 марта 2010

Я понимаю, что это старый вопрос, но хотел бы добавить немного. Я попал в ту же ситуацию, и по этой теме нет документации / блогов. Тем не менее, я нашел способ использовать собственный поставщик ресурсов с одним предупреждением. Предостережение в том, что я нахожусь в приложении MVC, поэтому у меня все еще есть HttpContext.GetLocalResourceObject(). Это метод, который asp.net использует для локализации элементов. Отсутствие объекта ресурса не мешает вам написать наше собственное решение, даже если это прямой запрос таблиц БД. Тем не менее я подумал, что на это стоит обратить внимание.

Хотя я не очень доволен следующим решением, похоже, оно работает. Для каждого атрибута проверки, который я хочу использовать, я наследую от указанного атрибута и перегружаю IsValid (). Украшение выглядит так:

[RequiredLocalized(ErrorMessageResourceType= typeof(ClassBeginValidated), ErrorMessageResourceName="Errors.GenderRequired")]
public string FirstName { get; set; } 

Новый атрибут выглядит так:

public sealed class RequiredLocalized : RequiredAttribute {

    public override bool IsValid(object value) {

        if ( ! (ErrorMessageResourceType == null || String.IsNullOrWhiteSpace(ErrorMessageResourceName) )   ) {
            this.ErrorMessage = MVC_HtmlHelpers.Localize(this.ErrorMessageResourceType, this.ErrorMessageResourceName);
            this.ErrorMessageResourceType = null;
            this.ErrorMessageResourceName = null;
        }
        return base.IsValid(value);
    }
}

Примечания

  • Вам необходимо украсить свой код производным атрибутом, а не стандартным
  • Я использую ErrorMessageResourceType для передачи типа проверяемого класса. Под этим я подразумеваю, что если я нахожусь в классе клиента и проверяю свойство FirstName , я передам typeof (customer) . Я делаю это, потому что в своей базе данных я использую полное имя класса (namespace + classname) в качестве ключа (так же, как URL страницы используется в asp.net).
    • MVC_HtmlHelpers.Localize - это просто оболочка для моего провайдера пользовательских ресурсов

(полу-украденный) вспомогательный код выглядит следующим образом ...

public static string Localize (System.Type theType, string resourceKey) {
    return Localize (theType, resourceKey, null);
}
public static string Localize (System.Type theType, string resourceKey, params object[] args) {
    string resource = (HttpContext.GetLocalResourceObject(theType.FullName, resourceKey) ?? string.Empty).ToString();
    return mergeTokens(resource, args);
}

private static string mergeTokens(string resource, object[] args)        {
    if (resource != null && args != null && args.Length > 0) {
        return string.Format(resource, args);
    }  else {
        return resource;
    }
}
3 голосов
/ 18 марта 2010

Я использовал свободное подтверждение для достижения этой цели. Это экономит мне много времени. Вот как выглядит мой Globalized validator. Это означает, что вы не используете аннотации данных, но иногда аннотации данных становятся немного большими и грязными.

Вот пример:

(Errors.Required, Labels.Email и Errors.AlreadyRegistered находятся в моей папке с глобальными ресурсами)

public class CreateEmployerValidator : AbstractValidator<CreateEmployerModel> {
    public RegisterUserValidator() { 
        RuleFor(m => m.Email)
            .NotEmpty()
            .WithMessage(String.Format(Errors.Required, new object[] { Labels.Email }))
            .EmailAddress()
            .WithMessage(String.Format(Errors.Invalid, new object[] { Labels.Email }))
            .Must(this.BeUniqueEmail)
            .WithMessage(String.Format(Errors.AlreadyRegistered,  new object[] { Labels.Email }));
    }

    public bool BeUniqueEmail(this IValidator validator, string email )  {
        //Database request to check if email already there?
        ...
    }    
}

Как я уже сказал, это аннулирование аннотаций данных форм только потому, что у меня уже слишком много аннотаций на моих методах!

2 голосов
/ 28 марта 2012

Я добавлю свои выводы, так как мне пришлось бороться с этим. Может быть, это кому-нибудь поможет.

Когда вы наследуете от RequiredAttribute, кажется, что он нарушает проверку на стороне клиента. Поэтому, чтобы исправить это, я реализовал IClientValidatable и реализовал метод GetClientValidationRules. Resources.GetResources - это статический вспомогательный метод, который у меня есть, который охватывает HttpContext.GetGlobalResourceObject.

Пользовательский обязательный атрибут:

public class LocalizedRequiredAttribute : RequiredAttribute, IClientValidatable 
{
    public LocalizedRequiredAttribute(string resourceName)
    {
        this.ErrorMessage = Resources.GetResource(resourceName);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType= "required"
        };
    }
}

Использование:

[LocalizedRequired("SomeResourceName")]
public string SomeProperty { get; set; }

И мой помощник по ресурсам, если кому-то интересно:

public class Resources
{
    public static string GetResource(string resourceName)
    {
        string text = resourceName;
        if (System.Web.HttpContext.Current != null)
        {
            var context = new HttpContextWrapper(System.Web.HttpContext.Current);
            var globalResourceObject = context.GetGlobalResourceObject(null, resourceName);
            if (globalResourceObject != null)
                text = globalResourceObject.ToString();
        }

        return text;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...