Каков наилучший способ локализовать ошибки аннотации без данных с помощью ASP.NET MVC 3?

#asp.net-mvc #validation #localization #business-logic

#asp.net-mvc #проверка #локализация #бизнес-логика

Вопрос:

С помощью аннотаций данных теперь легко локализовать сообщения об ошибках, используя файлы Resource.resx, например, такие:

 public class Student
{
    . . .

    [Required(ErrorMessageResourceName ="Required",
     ErrorMessageResourceType = typeof(StudentResources))]
    [StringLength(16)] 
    [Display(Name = "FirstName", ResourceType = typeof(StudentResources))]
    public string FirstName { get; set; }

    . . .
}
  

Теперь, допустим, я хочу проверить, произвел ли студент уже платеж за данный месяц и год:

 public bool CheckIfAlreadyPaid(Payment payment)
{
    return repository.GetPayments().Any(p => p.StudentId == payment.StudentId amp;amp;
                                        p.Month == payment.Month amp;amp;
                                        p.Year == payment.Year);
}
  

Если он уже произвел платеж, я делаю следующее на уровне моих сервисов:

 if (CheckIfAlreadyPaid(payment))
{
    modelState.AddModelError("AlreadyPaid",
    Resources.Views.Payment.PaymentCreateResources.AlreadyPaid);
}
  

Это работает, но я не уверен в том, что ссылаюсь на файл ресурсов внутри уровня сервисов.

Существует ли стандартный или лучший способ локализации сообщений об ошибках, которые не привязаны к свойствам модели (аннотации данных) — ошибкам, возникающим из правил бизнес-логики? Должен ли я по-прежнему добавлять эти ошибки в ModelStateDictionary?

Ответ №1:

Я согласен, я не думаю, что это должно быть на уровне сервиса. Похоже, что это можно либо поместить в пользовательский атрибут проверки данных, либо обработать каким-либо другим подходом на этом уровне (использование беглой проверки может быть хорошим вариантом). В любом случае, я думаю, пока проверка остается в самом приложении MVC, вам может быть удобно использовать файлы ресурсов для хранения сообщений.

Ответ №2:

Я сделал это по-другому. Service Уровень используется для проверки, был ли уже произведен платеж. В моем Controller я добавляю сообщение об ошибке проверки к объекту ModelState, передавая ему локализованный строковый ресурс. Теперь я чувствую себя более комфортно с этим подходом.

Вот код:

 /// <summary>
/// Performs validation of business logic...
/// </summary>
/// <param name="payment"></param>
/// <returns></returns>
private bool ValidatePayment(Payment payment)
{
    if (paymentService.IsPaymentMade(payment))
    {
        ModelState.AddModelError("AlreadyPaid", Localization.AlreadyPaid);
    }

    return ModelState.IsValid;
}
  

Редактировать:

В дополнение к моему ответу, я только сегодня обнаружил, что ValidationSummary @Html.ValidationSummary(true) делает именно то, что я хочу:

Html.ValidationSummary возвращает неупорядоченный список (элемент ul) сообщений проверки, которые находятся в ModelStateDictionary объекте, и необязательно отображает только ошибки уровня модели.

Я передаю true , и он будет отображать только ошибки уровня модели (ошибки аннотации без данных) в сводке только в верхней части страницы. Это здорово, но только если это сработает … 🙂

Я столкнулся с проблемой, когда мои пользовательские сообщения об ошибках, не привязанные к свойствам модели, не появлялись при настройке ValidationSummary(true) . Затем я поискал в Google и нашел этот пост. Я попробовал его решение, но оно не сработало. Затем я поискал еще немного и нашел эту ссылку в Google Books (Pro ASP.NET Платформа MVC 2 (автор Стивен Сандерсон).

Я попробовал то, что описано там, передав пустую строку в качестве ключа ( string.Empty ), и она выполнила свою работу.

 if(paymentService.IsPaymentMade(payment))
{
    ModelState.AddModelError(string.Empty, Localization.PaymentAlreadyCreated);
}