Лучший способ реализовать проверку «Требовать», если другое поле не равно нулю

У меня есть следующие два поля внутри моего представления: -

<div>

<span class="f">@Html.DisplayNameFor(model=>model.Firewall.ConsoleServerID)</span>

@Html.DropDownListFor(model =>model.Firewall.ConsoleServerID, ((IEnumerable<IT.Models.ITConsoleServer>)ViewBag.Servers).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Technology.Tag), 
Value = option.ConsoleServerID.ToString(),
Selected = (Model != null) && (Model.Firewall.ITConsoleServer != null) && (option.ConsoleServerID == Model.Firewall.ConsoleServerID)
}), "Choose...")
@Html.ValidationMessageFor(model =>model.Firewall.ConsoleServerID)

</div>

<div >
<span class="f">@Html.DisplayNameFor(model=>model.Firewall.ConsoleServerPort)</span> 

@Html.TextBoxFor(model => model.Firewall.ConsoleServerPort) 
@Html.ValidationMessageFor(model => model.Firewall.ConsoleServerPort) | 

The rule I want to implement is that both fields are NullAble, but if the user selects a ConsoleServerID , then he needs to add a Port . and if the user leave the ConsoleServerID null then he should not enter a Port number. So what is the best way to implement this scenario , so that I have both client side and server side validation ? Thanks

Изменить После установки защиты от дурака я столкнулся со следующими проблемами: -

  1. проверка на стороне клиента не выполняется, и проверка выполняется при проверке того, действительно ли состояние модели внутри моего класса контроллера

  2. если [RequiredIfNotEmpty] имеет значение false, то пользователь получит следующее сообщение: - Порт сервера консоли требуется из-за того, что идентификатор ConsoleServerID не пуст. Поэтому вместо имени поля, которое является тегом сервера консоли, будет отображаться идентификатор ConsoleServerID.

  3. если пользователь попытался отправить форму, в которой ConsoleServerID имеет значение null, я получу следующее исключение: -

Исключение System.Data.Entity.Validation.DbUnexpectedValidationException не было обработано кодом пользователя HResult=-2146233087 Message=Непредвиденное исключение возникло во время проверки «Консольного порта сервера» при вызове Foolproof.RequiredIfNotEmptyAttribute.IsValid. Подробности смотрите во внутреннем исключении. Source=EntityFramework StackTrace: в System.Data.Entity.Internal.Validation.ValidationAttributeValidator.Validate(EntityValidationContext entityValidationContext, свойство InternalMemberEntry) в System.Data.Entity.Internal.Validation.PropertyValidator.Validate(EntityValidationContext entityValidationContext, InternalMemberEntry property) в System.Data.Entity.Internal.Validation.PropertyValidator.Validate(EntityValidationContext entityValidationContext, InternalMemberEntry property) в System.Data.Entity.Internal.Validation.PropertyValidator.Validate Data.Entity.Internal.Validation.EntityValidator.ValidateProperties (EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty, элементы List1 validationErrors) at System.Data.Entity.Internal.Validation.TypeValidator.Validate(EntityValidationContext entityValidationContext, InternalPropertyEntry property) at System.Data.Entity.Internal.Validation.EntityValidator.Validate(EntityValidationContext entityValidationContext) at System.Data.Entity.Internal.InternalEntityEntry.GetValidationResult(IDictionary2) в System.Data.Entity.DbContext.ValidateEntity (параметры DbEntityEntry entityEntry, IDictionary2 items) at System.Data.Entity.DbContext.GetValidationErrors() at System.Data.Entity.Internal.InternalContext.SaveChanges() at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() at System.Data.Entity.DbContext.SaveChanges() at TMS.Models.Repository.Save() in c:\Users\Administrator\Desktop\New folder (19)\TMS\TMS\TMS\Models\Repository.cs:line 4614 at TMS.Controllers.FirewallController.Edit(FirewallJoin fj, FormCollection formValues) in c:\Users\Administrator\Desktop\New folder (19)\TMS\TMS\TMS\Controllers\FirewallController.cs:line 869 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2) в System.Web.Mevc.ControllerActionControlInvokerth.Invoke controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass81.b__7(IAsyncResult _) в System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End() в System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInv okeActionMethod(IAsyncResult asyncResult) в System.Web.Mvc.Async.AsyncControllerActionInvoker.‹>c__DisplayClass37.‹>c__DisplayClass39.b__33() в System.Web.Mvc.Async.AsyncControllerActionInvoker.‹>c__DisplayClass4f.b__49() InnerException: System.NotImplementedException HResult=-2147467263 Сообщение=Метод или операция не реализованы. Source = MVC Foolproof Validation StackTrace: в Foolproof.ModelAwareValidationAttribute.IsValid (значение объекта) в System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid (значение объекта, ValidationContext validationContext) в System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult (значение объекта, ValidationContext validationContext) ) в System.Data.Entity.Internal.Validation.ValidationAttributeValidator.Validate(EntityValidationContext entityValidationContext, свойство InternalMemberEntry) InnerException:


person john Gu    schedule 24.04.2014    source источник
comment
Мне нравится надежный stackoverflow.com/questions/12843282 /   -  person Matt Bodily    schedule 24.04.2014
comment
но будет ли защита от дурака также реализовывать проверку на стороне сервера? Так что, если хакер пройдет проверку на стороне клиента, защита от ошибок должна проверить проверку на сервере?   -  person john Gu    schedule 24.04.2014
comment
Да, это будет. просто выполните if(ModelState.IsValid) на контроллере, и он вернет false, если ваше условие не выполнено   -  person Matt Bodily    schedule 24.04.2014
comment
я установил защиту от дурака и добавил следующее [RequiredIfNotEmpty(ConsoleServerID)] в ConsoleServerPort, но я отметил, что проверка на стороне клиента не будет выполняться, вся проверка будет выполняться внутри контроллера, можете ли вы посоветовать   -  person john Gu    schedule 24.04.2014
comment
также, если ConsoleServerId имеет значение null , будет возбуждено исключение.   -  person john Gu    schedule 24.04.2014
comment
вы можете добавить атрибут отображаемого имени к свойству вашей модели, которое должно изменить ваше сообщение проверки на имя, которое вы хотите. Надеюсь, form.valid исправит другие проблемы, как только мы сможем заставить это работать.   -  person Matt Bodily    schedule 24.04.2014
comment
я уже определил отображаемое имя для свойства, но кажется, что защита от дурака не распознала его ..   -  person john Gu    schedule 24.04.2014


Ответы (2)


Мы делаем много вызовов ajax. Как я запускаю проверку на стороне клиента

$('#btnClick').on('click', function(){
     if ($('form').valid()) {
         $.ajax({
         //call here
         });
     }
});

form.valid запускает проверку формы

person Matt Bodily    schedule 24.04.2014
comment
но мне нужен более общий подход, который я могу повторно использовать во всех связанных представлениях. FoolProof хорош, но я столкнулся с проблемой при его использовании. - person john Gu; 24.04.2014
comment
это не обязательно должен быть вызов ajax посередине. Просто настройте его так, чтобы он срабатывал при нажатии кнопки или другого селектора, и запустите form.valid. Убедитесь, что у вас есть тег формы вокруг содержимого, которое вы хотите проверить. - person Matt Bodily; 24.04.2014
comment
не могли бы вы проверить мою правку, пожалуйста - person john Gu; 24.04.2014

Лучшим способом было бы поместить эту логику в вашу модель.

В вашей ViewModel создайте логическое свойство следующим образом:

public bool IsAddingPortRequired
{
   get
   {
       return ConsoleServerID != null;
   }
}

Затем используйте свой атрибут RequiredIf следующим образом:

[RequiredIf("IsAddingPortRequired", true, ErrorMessage = "You must add a port Number")]
person meda    schedule 24.04.2014
comment
так почему я не могу использовать защиту от дурака вместо этого? и где мне нужно создать ISAddingPortRequired? внутри самого класса модели? - person john Gu; 24.04.2014
comment
Хм? RequiredIf надежен, поскольку во встроенной функции этого нет. да поставь прямо там где у тебя ConsoleServerID - person meda; 24.04.2014
comment
ага, хорошо, извините за это, но почему я не могу использовать [RequiredIfNotEmpty] тогда? - person john Gu; 24.04.2014
comment
что я не уверен (никогда не пробовал), может быть, null и empty - это не одно и то же? - person meda; 24.04.2014
comment
@johnG у тебя была возможность попробовать? это должно решить вашу проблему - person meda; 24.04.2014