У меня есть модель Entity Framework, к которой я пытаюсь добавить валидацию, но я нашел себя в некоторой ловушке 22. Здесь 1001 *
У меня есть частичный класс, связанный с моделью, сгенерированной сущностью, в отдельном файле, который выглядит следующим образом ...
[MetadataType(typeof(cmsNodeMetadata))]
public partial class cmsNode : IDataErrorInfo
{
... Code ....
#region IDataErrorInfo
private readonly Dictionary<string, string> _errors = new Dictionary<string, string>();
private readonly Entities _db = new Entities();
public string this[string columnName]
{
get
{
if (_errors.ContainsKey(columnName))
return _errors[columnName];
return string.Empty;
}
}
public string Error { get; private set; }
partial void OnNameChanging(string value)
{
var valueIsUnique = (from n in _db.cmsNodes
where n.ParentId == ParentId
&& n.Name.Trim().ToLower() == value.Trim().ToLower()
select n.Name).Count() == 0;
if (!valueIsUnique)
{
_errors.Add("Name", "The name must be unique");
}
}
#endregion
}
... и я добавил проверку в отдельный класс, который прекрасно работает.
public class cmsNodeMetadata
{
[StringLength(150), Required]
[Display(Name = "Name")]
public string Name;
}
Я работаю с MVC 3, и мой контроллер, использующий этот класс, выглядит следующим образом ...
[HttpPost]
public ActionResult Edit(cmsNode cmsnode)
{
if (ModelState.IsValid)
{
var obj = _db.cmsNodes.Single(c => c.Id == cmsnode.Id);
obj.Name = cmsnode.Name;
obj.Alias = cmsnode.Name.Slugify(150);
_db.SaveChanges();
return Content(Boolean.TrueString);
}
return Content("Please review your form");
}
Мое мнение, использующее этот класс, выглядит следующим образом ...
@model Project.com.Admin.Models.cmsNode
@using (Ajax.BeginForm("Create", "Node", null, new AjaxOptions
{
UpdateTargetId = "create-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "createSuccess"
}, new { @id = "createNodeForm" }))
{
@Html.ValidationSummary(true)
<div id="create-message" class="error invisible"></div>
<fieldset>
<legend>Create New Navigation Tree Node</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
@Html.HiddenFor(model => model.ParentId)
@Html.HiddenFor(model => model.Alias)
</fieldset>
}
Хорошо, вот в чем проблема. Мне нужно добавить некоторую пользовательскую проверку в этот класс (cmsNode), который проверяет, чтобы убедиться, что имя еще не занято ни одним другим узлом с таким же ParentId.
Для этого мне нужно получить дескриптор члена экземпляра с именем ParentId. К сожалению, я не могу понять, как получить дескриптор экземпляра, который я проверяю, из класса cmsNodeMetadata.
Поэтому я попытался изменить свой подход, переопределив метод onChanging для свойства Name в моем классе cmsNode и добавив туда проверку, но это вызвало еще одну проблему. Хотя я могу проверить свойство name с помощью переопределенного метода проверки, я получаю исключения, когда имя возвращается неустановленным из представления, потому что моя модель сущности не исключает нулевые значения для свойства Name, и я не могу его перехватить, потому что содержимое представления преобразуется в тип модели во входном параметре моего контроллера.
Затем я попытался использовать оба метода, кроме метода проверки MetadatatType и onChanging, но метод onChanging игнорируется.
Я понимаю, что мог бы решить эту проблему следующим образом:
- Я мог бы изменить тип возвращаемого значения контроллера на коллекцию FormCollection, объект dto, или напрямую определить входные свойства и использовать, а затем создать объект в контроллере после того, как я проверю нулевое значение, которое вполне подходит.
Мне просто интересно, я что-то упустил? Есть ли способ проверить свойство и проверить наличие повторяющихся имен с помощью ValidationAttributes? Могу ли я предотвратить возвращение Nulls из моего поля зрения? Почему метод onChanging в платформе сущностей не имеет опции Cancel для предотвращения установки элемента, если проверка не работает? Спасибо за вашу помощь!