Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 在ASP.NETMVC3中创建条件表单的正确方法是什么?_Asp.net Mvc 3 - Fatal编程技术网

Asp.net mvc 3 在ASP.NETMVC3中创建条件表单的正确方法是什么?

Asp.net mvc 3 在ASP.NETMVC3中创建条件表单的正确方法是什么?,asp.net-mvc-3,Asp.net Mvc 3,问题概述: 我想在我的形式中有一些条件逻辑。用户通过单选按钮进行选择,根据选择,我想隐藏一些字段并显示一些其他字段。这也会影响验证(不应验证隐藏字段)。我认为这是一个典型的问题,但我找不到任何例子,我自己的解决方案似乎有很多管道 我的实际问题: 让我们从viewmodel类开始(根据这个问题的需要进行了一些简化): 在我的场景模型的创建/编辑视图中,我有一个相当大的表单,由3个选项卡组成。在第三个选项卡上,我根据响应模型显示局部视图。这就是我想要的条件逻辑ResponseType属性是表单上的单

问题概述:

我想在我的形式中有一些条件逻辑。用户通过单选按钮进行选择,根据选择,我想隐藏一些字段并显示一些其他字段。这也会影响验证(不应验证隐藏字段)。我认为这是一个典型的问题,但我找不到任何例子,我自己的解决方案似乎有很多管道

我的实际问题:

让我们从viewmodel类开始(根据这个问题的需要进行了一些简化):

在我的
场景
模型的创建/编辑视图中,我有一个相当大的表单,由3个选项卡组成。在第三个选项卡上,我根据
响应
模型显示局部视图。这就是我想要的条件逻辑
ResponseType
属性是表单上的单选按钮。它可以有两个值:正常值和错误值。如果出现错误,我希望显示并验证
ErrorCode
ErrorDescr
属性。在正常情况下,我只想显示和验证
状态
属性

我的解决方案:

  • 在响应部分视图中,我连接了一些jquery.hide()和.show()调用,以隐藏/显示相关的输入元素
  • 我修改了jquery不引人注目的验证脚本,以阻止它验证隐藏字段()
  • 在Scenario controller中,我有如下代码:

    public ActionResult Edit(int id, Scenario scenario)
    {
       Response response=scenario.Response;
       if (response.ResponseType != null)
       {
          if (response.ResponseType == "NORMAL")
          {
             //in this case remove validation for errorcode
             this.ModelState.Remove("Response.ErrorCode");
          }
          else
          {
             //in this case remove validation for state
             this.ModelState.Remove("Response.State");
          }
       }
       if (ModelState.IsValid)
       {
           //map to entity and save to database
       }
    }
    

  • 这是一个非常丑陋的管道(尤其是控制器代码-使用字符串键从ModelState中删除项…没有类型安全性等),肯定有更好的方法吗?

    您可以尝试在
    Response
    类中继承
    IValidateableObject
    ,并在
    Validate
    中执行条件验证。像这样:

    public class Response : IValidateableObject
    {
        [Required]
        public string ResponseType { get; set; }
        public string State { get; set; }   
        public string ErrorCode { get; set; }
        public string ErrorDescr { get; set; }
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (ResponseType == "NORMAL")
            {
                if (State.IsNullOrWhiteSpace)
                    yield return new ValidationResult("State is required", new [] { "State" });
            }
    
            // additional validations...
        }
    }
    
    公共类响应:IValidTeableObject
    {
    [必需]
    公共字符串响应类型{get;set;}
    公共字符串状态{get;set;}
    公共字符串错误代码{get;set;}
    公共字符串ErrorDescr{get;set;}
    公共IEnumerable验证(ValidationContext ValidationContext)
    {
    if(ResponseType==“正常”)
    {
    if(State.IsNullOrWhiteSpace)
    返回新的ValidationResult(“状态是必需的”,新[]{“状态”});
    }
    //其他验证。。。
    }
    }
    
    这已经很旧了,我不喜欢在没有答案的情况下闲逛,所以我会自己回答

    正确的解决方案是实现自定义验证属性,并实现IClientValidable接口。这满足了所有要求-控制器内部没有管道,客户端验证一致

    现在,我甚至可能不会自己实现它——我会使用一个现有的库,比如提供了一个好的、灵活的RequiredIf属性的库:

    public class Response
    {
        [Required]
        public string ResponseType { get; set; }
    
        [RequiredIf("ResponseType == 'NORMAL'"]
        public string State { get; set; }
    
        [RequiredIf("ResponseType == 'ERROR'"]
        public string ErrorCode { get; set; }
    
        public string ErrorDescr { get; set; }
    }
    

    通过在Global.asax中添加几行代码并包含带有验证器的javascript来配置属性后,该属性可以在服务器端和客户端工作。您可以在项目页面上阅读详细信息。

    不幸的是,以这种方式进行的验证在客户端不起作用。我真的不喜欢这样,因为它引入了两个阶段的验证效果(用户根据客户端验证正确填写表单,提交表单,嘿,他得到了一些新错误…糟糕的用户体验)。
    public class Response
    {
        [Required]
        public string ResponseType { get; set; }
    
        [RequiredIf("ResponseType == 'NORMAL'"]
        public string State { get; set; }
    
        [RequiredIf("ResponseType == 'ERROR'"]
        public string ErrorCode { get; set; }
    
        public string ErrorDescr { get; set; }
    }