Обработка обязательных полей в ASP.NET MVC при использовании Entity Framework
хорошо, эта проблема действительно проникает под мою кожу. Позвольте мне начать с описания моего приложения в пошаговом формате.
сначала у меня есть модель, сгенерированная 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
как вы можете видеть, сообщение об ошибке не появится. Однако он правильно проверил поле как недопустимое. Если я помещаю туда значение, то оно проверяет просто отлично. Я сделал много исследований по этому вопросу и вот, что я знаю:
в причина, по которой вы не можете настроить сообщение об ошибке, отображаемое для обязательных полей, заключается в том, что свойство model не имеет значения null. Поскольку он не nullable, попытка привязать к нему значение null вызывает исключение. В MVC ласточки это excepion и доверие модели как надо. Сообщение генерируется везде, где происходит это исключение. Я не знаю, генерируется ли сообщение EF или MVC (я предполагаю, что MVC, поскольку он отвечал за проглатывание исключения в первую очередь). Я не знаю как настроить это сообщение. Как вы можете видеть, он всегда говорит, что "значение" недопустимо."что, я полагаю, не совсем ужасно, но на самом деле не очень удобно.
он попадает в валидатор моего имени и проверяет, является ли ваше имя "fred" просто прекрасным, потому что не возникает никаких исключений. Что касается EF, переданное значение в порядке. Это не так, пока он не доберется до моего OnAuthorChanging
метод, который он понимает, что это не хорошо. Это правильное поведение и работает просто отлично.
если я брошу исключение в моих событиях OnChanging вместо добавления в my 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 " недопустимо.". С требуемыми полями просто значение равно null, поэтому между одинарными кавычками нечего ставить.
несколько человек (такой Гай!--12-->) предложите вам просто установить свойство nullable в вашей модели. Это неприемлемое решение. Одна из причин, почему нет, такова:
ошибка 3031: проблема в сопоставлении фрагменты, начинающиеся на линии 313:необнуляемый столбец Посткомменты.Тело в таблице PostComments сопоставляется с nullable свойство сущности.
кроме того, установка nullable просто не будет работать на ненулевых типах, таких как int, а переключение int на nullable int-это Гадкий бардак, в который я даже не хочу попасть.
суть в том, что я хочу обрабатывать эти исключения из EF сам или, по крайней мере, настроить сообщение, которое он генерирует, но я не знаю, как. Я совсем запутался. Все, что я хочу сделать, это настроить сообщение о том, что я считал очень простой проверкой модели!
любая помощь очень ценится.
2 ответов
MVC-это проверка модели на основе типа не nullible, как вы обнаружили. Это добавление ошибок в ModelState перед запуском пользовательской проверки.
у меня было это раньше, и я обошел его, пройдя через Modelstate в начале действия и удалив все, а затем выполнив свою пользовательскую проверку (плохо!!)
затем найдено, даже если вы не используете аннотации данных в качестве основной формы проверки, вы можете настроить сообщение, которое добавление [обязательно к типу non nullible в классе buddy и указание сообщения.
Это что-то вроде этого:
[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;}
}
}
Я начал смотреть на fluent validation (http://fluentvalidation.codeplex.com) для mvc, и они, похоже, отключают проблему в глобальном масштабе.asax, в on application_start (), добавив строку
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
но я могу ошибаться на этот счет.
Я знаю, что это не совсем то, что вы спросили, но я только что закончил проект на прошлой неделе, в котором я использовал проверку на стороне клиента MVC 3 с аннотациями данных и ненавязчивым javascript. Его довольно полный рот, но работает замечательно. Вы можете настроить regex, maxlenght, required и все другие атрибуты, и он проверяет все это на клиенте. Это делает проверку формы намного быстрее для пользователя.
вот некоторые полезные ссылки с примерами, здесь, здесь и очень хороший образец MSDN для загрузки и опробования здесь
надеюсь, что это помогает,