在某些情况下禁用必需的验证属性

Ale*_*nor 129 c# asp.net-mvc data-annotations asp.net-mvc-3

我想知道是否可以在某些控制器操作中禁用Required validation属性.我想知道这是因为在我的一个编辑表单中,我不需要用户输入他们之前已经指定的字段的值.然而,我然后实现逻辑,当它们输入值时,它使用一些特殊的逻辑来更新模型,例如散列值等.

有关如何解决这个问题的任何消息?

编辑:
是的客户端验证是一个问题,因为它不允许他们提交表单而不输入值.

Dar*_*rov 76

使用视图模型可以轻松解决此问题.视图模型是专门针对给定视图的需求而定制的类.例如,在您的情况下,您可以使用以下视图模型:

public UpdateViewView
{
    [Required]
    public string Id { get; set; }

    ... some other properties
}

public class InsertViewModel
{
    public string Id { get; set; }

    ... some other properties
}
Run Code Online (Sandbox Code Playgroud)

将在其相应的控制器操作中使用:

[HttpPost]
public ActionResult Update(UpdateViewView model)
{
    ...
}

[HttpPost]
public ActionResult Insert(InsertViewModel model)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 不,我们通常没有`Update(FormCollection集合)`,至少我从来没有.我总是定义并使用特定的视图模型:`Update(UpdateViewView model)`. (4认同)

Adr*_*ith 55

如果您只想在客户端禁用单个字段的验证,则可以按如下方式覆盖验证属性:

@Html.TexBoxFor(model => model.SomeValue, 
                new Dictionary<string, object> { { "data-val", false }})
Run Code Online (Sandbox Code Playgroud)

  • 通过jQuery为我工作的是:$("#SomeValue").removeAttr("data-val-required"); (18认同)
  • `@Html.TexBoxFor(model => model.SomeValue,new {data_val = false})` - 更容易阅读IMO. (15认同)
  • 我喜欢这种方法,但我需要使用以下方法重新解析表单验证属性:$('form').removeData('unobtrusiveValidation'); $( '形式')removeData( '校验'); $ .validator.unobtrusive.parse('表单的选择器'); (6认同)
  • 如果你想通过jQuery禁用它:`$(".search select").attr('data-val',false);` (4认同)

Phi*_*lac 39

我知道这个问题很久以前就得到了回答,接受的答案实际上就是做了.但是有一件事困扰着我:必须复制2个模型才能禁用验证.

这是我的建议:

public class InsertModel
{
    [Display(...)]
    public virtual string ID { get; set; }

    ...Other properties
}

public class UpdateModel : InsertModel
{
    [Required]
    public override string ID
    {
        get { return base.ID; }
        set { base.ID = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您不必费心进行客户端/服务器端验证,框架将按照预期的方式运行.此外,如果[Display]在基类上定义属性,则不必在您的基类中重新定义它UpdateModel.

你仍然可以用同样的方式使用这些类:

[HttpPost]
public ActionResult Update(UpdateModel model)
{
    ...
}

[HttpPost]
public ActionResult Insert(InsertModel model)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)


jps*_*jps 23

您可以在控制器操作中使用以下内容删除属性的所有验证.

ModelState.Remove<ViewModel>(x => x.SomeProperty);
Run Code Online (Sandbox Code Playgroud)

@Ian关于MVC5 评论

以下仍然是可能的

ModelState.Remove("PropertyNameInModel");
Run Code Online (Sandbox Code Playgroud)

有点烦人,你失去了使用更新的API的静态类型.您可以通过创建HTML帮助程序实例并使用NameExtensions方法来实现类似于旧方法的操作.


ntt*_*akr 14

我个人倾向于使用Darin Dimitrov在他的解决方案中展示的方法.这使您能够使用数据注释方法进行验证,并在与当前任务相对应的每个ViewModel上具有单独的数据属性.要最大限度地减少模型和视图模型之间的复制工作量,您应该查看AutoMapper或ValueInjecter.两者都有各自的优势,所以请检查两者.

另一种可能的方法是从IValidatableObject派生您的viewmodel或模型.这使您可以选择实现Validate函数.在validate中,您可以返回ValidationResult元素列表,也可以为您在验证中检测到的每个问题发出一个yield return.

ValidationResult包含一条错误消息和一个包含字段名的字符串列表.错误消息将显示在输入字段附近的位置.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
  if( NumberField < 0 )
  {
    yield return new ValidationResult( 
        "Don't input a negative number", 
        new[] { "NumberField" } );
  }

  if( NumberField > 100 )
  {
    yield return new ValidationResult( 
        "Don't input a number > 100", 
        new[] { "NumberField" } );
  }

  yield break;
}
Run Code Online (Sandbox Code Playgroud)


int*_*t-i 14

客户端 对于禁用表单验证,下面给出了基于我的研究的多个选项.其中一个希望能为你工作.

选项1

我更喜欢这个,这对我来说非常合适.

(function ($) {
    $.fn.turnOffValidation = function (form) {
        var settings = form.validate().settings;

        for (var ruleIndex in settings.rules) {
            delete settings.rules[ruleIndex];
        }
    };
})(jQuery); 
Run Code Online (Sandbox Code Playgroud)

并调用它

$('#btn').click(function () {
    $(this).turnOffValidation(jQuery('#myForm'));
});
Run Code Online (Sandbox Code Playgroud)

选项2

$('your selector here').data('val', false);
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
Run Code Online (Sandbox Code Playgroud)

选项3

var settings = $.data($('#myForm').get(0), 'validator').settings;
settings.ignore = ".input";
Run Code Online (Sandbox Code Playgroud)

选项4

 $("form").get(0).submit();
 jQuery('#createForm').unbind('submit').submit();
Run Code Online (Sandbox Code Playgroud)

选项5

$('input selector').each(function () {
    $(this).rules('remove');
});
Run Code Online (Sandbox Code Playgroud)

服务器端

创建属性并使用该属性标记您的操作方法.自定义此选项以适应您的特定需求.

[AttributeUsage(AttributeTargets.All)]
public class IgnoreValidationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var modelState = filterContext.Controller.ViewData.ModelState;

        foreach (var modelValue in modelState.Values)
        {
            modelValue.Errors.Clear();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里描述了一种更好的方法动态启用/禁用mvc服务器端验证


Ada*_*SFT 7

我认为最干净的方法是禁用客户端验证,在服务器端,您需要:

  1. ModelState ["SomeField"].Errors.Clear(在控制器中或创建一个动作过滤器以在执行控制器代码之前删除错误)
  2. 当您检测到违反检测到的问题时,从控制器代码中添加ModelState.AddModelError.

看起来即使是自定义视图模型也不会解决问题,因为那些"预先回答"字段的数量可能会有所不同.如果他们不这样做自定义视图模型可能确实是最简单的方法,但使用上述技术可以解决您的验证问题.


Mik*_*_II 5

这是评论中其他人的答案......但它应该是一个真正的答案:

$("#SomeValue").removeAttr("data-val-required")

在具有该[Required]属性的字段的MVC 6上进行测试

回答从/sf/users/5136771/上面偷来的