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