Обработка обязательных полей в ASP.NET MVC при использовании Entity Framework - PullRequest
7 голосов
/ 19 марта 2011

Хорошо, эта проблема действительно у меня под кожей.Позвольте мне начать с описания моего приложения в пошаговом формате.

Сначала у меня есть модель, созданная в Entity Framework.В нем есть следующие сущности:

http://www.codetunnel.com/EFEntities.jpg

Теперь, чтобы реализовать проверку сущности, я использую частичные классы и обрабатываю хуки OnChanging, которые предоставляет EF.Вот пример частичного класса PostComment:

namespace CodeTunnel.Domain.Models
{
    public partial class PostComment : IDataErrorInfo
    {
        private Dictionary<string, string> _errors = new Dictionary<string, string>();

        partial void OnAuthorChanging(string value)
        {
            //Validating anything but required value works fine.
            //Like this pseudo-validator.
            if (value.ToLower() != "fred")
                _errors.Add("Author", "Sorry, your name must be Fred.");
        }

        partial void OnBodyChanging(string value)
        {
            //Required value validation does not work, I will tell you why below.
            if (string.IsNullOrEmpty(value))
                _errors.Add("Body", "Body is required.");
        }

        #region -= IDataErrorInfo methods =-

        public string Error
        {
            get { return string.Empty; }
        }

        public string this[string columnName]
        {
            get
            {
                if (_errors.ContainsKey(columnName))
                    return _errors[columnName];
                return string.Empty;
            }
        }

        #endregion
    }
}

Обратите внимание, что мой класс наследуется от IDataErrorInfo.MVC проверяет это на наличие ошибок проверки по умолчанию.Если он находит что-либо, он делает недействительной модель и использует сохраненные ошибки в качестве сообщений для помощников проверки в представлении.Я почти уверен, что когда EF выдает исключение, этот словарь даже не заполняется значением этого свойства.На самом деле, я даже не уверен, что MVC заходит так далеко, что ищет значение после обнаружения и аннулирования модели после сгенерированного EF исключения.

Вот снимок экрана проблемы, включая примерпсевдо-валидатор, чтобы вы могли видеть, что он работает:

http://www.codetunnel.com/ValidationError.jpg

Как видите, сообщение об ошибке не появилось.Тем не менее, он правильно подтвердил поле как недействительное.Если я добавлю туда значение, то это будет хорошо.Я провел МНОГИЕ исследования по этой проблеме, и вот что я знаю:

Причина, по которой вы не можете настроить сообщение об ошибке, отображаемое для обязательных полей, заключается в том, что свойство модели не имеет значения NULL.Поскольку он не может быть обнуляемым, попытка связать с ним нулевое значение вызывает исключение.MVC проглатывает это исключение и делает модель недействительной, как следует.Сообщение генерируется везде, где возникает это исключение.Я не знаю, генерируется ли сообщение EF или MVC (я предполагаю, что MVC, так как он был ответственен за проглатывание исключения в первую очередь).Я не знаю, как настроить это сообщение.Как вы можете видеть, он всегда говорит: «Значение» недопустимо ».что, я полагаю, не совсем ужасно, но на самом деле это не очень удобно для пользователя.

Он попадает в мой валидатор имени и проверяет, хорошо ли ваше имя "fred", потому что исключение не выдается.Что касается EF, то переданное значение в порядке.Только когда он доходит до моего OnAuthorChanging метода, он понимает, что это не хорошо.Это правильное поведение и работает отлично.

Если я добавлю исключение в мои события OnChanging вместо добавления в свой словарь IDataErrorInfo, я могу создать такое же сообщение проверки, только оно помещает введенное значение междуодинарные кавычки.Пример:

    partial void OnAuthorChanging(string value)
    {
        if (value.ToLower() != "fred")
            //_errors.Add("Author", "Sorry, your name must be Fred.");
            throw new Exception("Sorry, your name must be Fred.");
    }

Этот код показывает это сообщение, когда в качестве значения для Автора вводится «test»: «Значение« test »недопустимо.».С обязательными полями просто значение равно нулю, поэтому между одинарными кавычками нечего ставить.

Несколько человек ( как этот парень ) предлагают просто установить для свойства значение nullableв твоей модели.Это НЕ приемлемое решение.Одна из причин, по которой это не так:

Ошибка 3031: проблема в отображении фрагментов, начинающихся со строки 313. Ненулевой столбец PostComments.Body в таблице PostComments сопоставляется со свойством объекта, допускающим значение NULL.

Кроме того, установка nullable просто не будет работать с необнуляемыми типами, такими как int, а переключение int на nullable int - отвратительный беспорядок, в который я даже не попаду.

Суть в том, что я хочу обработать эти исключения из EF самостоятельно или, по крайней мере, настроить сообщение, которое оно генерирует, но я не знаю как.Я полностью потерян.Все, что я хочу сделать, это настроить сообщение о том, что я считал очень простой проверкой модели!

Любая помощь очень ценится.

Ответы [ 2 ]

8 голосов
/ 19 марта 2011

MVC проверяет вашу модель, основываясь на том, что тип является недействительным, как вы обнаружили. Это добавляет ошибки в ModelState перед выполнением пользовательской проверки.

У меня было это раньше, и я обошел его, перебрав Modelstate в начале действия и удалив все, а затем выполнил мою собственную проверку (плохо !!)

Затем обнаруживается, даже если вы не используете аннотации данных в качестве основной формы проверки, вы можете настроить выдаваемое сообщение, добавив [Обязательный для недопустимого типа в классе собеседника и укажите сообщение.

Это примерно так:

[MetadataType(typeof(YourClassMetadata))]
public partial class YourClass
{       
  //buddyclass to entity class
  class YourClassMetadata 
  {
    [Required(ErrorMessage="Your custom overriding error message")]
    public int NonNullablePropertyThatIsGivingYouProblems {get;set;}
  }
}

Я начал смотреть на свободную проверку (http://fluentvalidation.codeplex.com) для mvc, и они, кажется, отключают проблему в global.asax в application_start (), добавляя строку

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

но я могу ошибаться.

0 голосов
/ 19 марта 2011

Я знаю, что это не совсем то, что вы просили, но я только что закончил проект на прошлой неделе, в котором я использовал MVC 3 Client Side Validation с аннотациями данных и ненавязчивым javascript. Это довольно глоток, но прекрасно работает. Вы можете настроить регулярное выражение, maxlenght, required и все другие атрибуты, и это проверяет все это на клиенте. Это делает проверку формы намного быстрее для пользователя.

вот несколько полезных ссылок с примерами, здесь , здесь и очень хороший пример MSDN, который можно загрузить и попробовать здесь

надеюсь, это поможет,

...