如何防止隐藏字段干扰MVC中的服务器端验证?

时间:2014-05-22 19:01:56

标签: c# .net asp.net-mvc server-side-validation

我有一个部分视图,它根据视图模型显示许多输入。在某些情况下,某些输入不会由局部视图呈现,但仍在视图模型中使用[Required]属性进行修饰。因此,当表单回发到我的控制器时,ModelState.IsValid返回false。有没有办法绕过这个?

4 个答案:

答案 0 :(得分:1)

我建议将验证与基础模型分开。

public class MyModel
{
  public string MyString { get; set; }
  public string MyHiddenField { get; set; }
}

public interface IMyModel_ValidateMystringOnly
{
  [Required]
  string MyString { get; set; }
}

[MetadataType(TypeOf(IMyModel_ValidateMystringOnly))]
public class MyModel_ValidateMystringOnly : MyModel

这允许您创建任意数量的验证类型,并且只在您需要时验证您想要的内容。

public ActionResult ShowMyModel()
{
  var model = new MyModel(); // or Respository.GetMyModel() whatever..

  View(model);
}

public ActionResult ValidateModel(MyModel_ValidateMystringOnly model)
{
  if (ModelState.IsValid)
  {
    // Hey Validation!
  }

  // MyModel_ValidateMyStringOnly is a MyModel 
  // so it can be passed to the same view!
  return View("ShowMyModel", model);
}

这只是一个例子,但应该明确如何在有或没有验证的情况下重复使用相同的模型。

答案 1 :(得分:1)

您可以使用Foolproof有条件地验证字段。这样,只有在需要时才需要它们,正如您在链接示例中所看到的那样。

private class Person
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    public bool Married { get; set; }

    [RequiredIfTrue("Married")]
    public string MaidenName { get; set; }
}

在此示例中,如果MaidenName

ModelState.IsValid只会将您的Married == true更改为false

答案 2 :(得分:1)

您应始终将VIEW模型与DOMAIN模型分开。这有一个很好的理由,它与安全性有关。当您使用域模型作为视图模型时,您很容易受到叠加和/或下冲击攻击。您可以在以下页面上阅读更多相关信息:

  1. http://odetocode.com/blogs/scott/archive/2012/03/12/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx
  2. http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx
  3. https://hendryluk.wordpress.com/tag/asp-net-mvc/
  4. 简而言之,如果您不需要某个字段,那么它就不应该在您的视图模型中。您应该转换 - 将您的视图模型映射到域模型。虽然它可能很乏味,但它可以使您的应用程序更加安全。您可以使用库来帮助您进行映射,例如Automapper。

    编辑:从我最初的答案开始,我得出结论,处理这种情况的最简单方法是让你的视图模型实现IValidatableObject接口,然后在Validate方法中编写验证逻辑。它不会为您提供客户端验证,但它是完成自定义/基于场景的验证的最有效和最简洁的方法,而无需编写自己的自定义过滤器。

    您可以在此处详细了解:http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3

答案 3 :(得分:1)

我根据特定的DropDown或单选按钮选择稍微改变了表单。

在检查ModelState.IsValid之前,在您的Action方法中,您可以执行ModelState.Remove("Object.PropertyName")

之类的操作

注意 :属性名称应与呈现给客户端的ID相同。用一个 ”。”任何下划线。

    If isSomeCondition Then
        ModelState.Remove("Property1")
        ModelState.Remove("Property2")
    End If

    If ModelState.IsValid() Then
       ...
    End If