2014-05-22 35 views
0

我有一个基于视图模型显示许多输入的局部视图。在某些情况下,其中一些输入不是由局部视图渲染的,但仍在视图模型中使用[Required]属性进行修饰。因此,当表单被发回给我的控制器时,ModelState.IsValid返回false。有没有办法绕过这个?如何防止隐藏字段干扰MVC中的服务器端验证?

+1

我要说的是,你应该改变你的视图模型,但很难在不知道的情况说。您可以手动“从ModelState中删除错误”,请参阅:http://stackoverflow.com/questions/14008561/is-there-a-strongly-named-way-to-remove-modelstate-errors-in-asp-net- mvc –

+0

当帖子内容绑定到视图模型时,字段的源是输入[type = hidden]还是input [type = text]并不重要。如果有一个值,它将被绑定,否则不会。之后将进行模型验证。 – gustavodidomenico

+0

mvc不验证该字段,它正在验证该类。所以如果你的类有一个必需的属性,并且你发布了一个'x'类,它不会是有效的,你必须手动删除它或创建另一个没有所需文件的类 –

回答

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

您可以使用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

1

你应该总是您的视图模型从你的域模型分开。这有一个很好的理由,它与安全性有关。当您使用域模型作为视图模型时,您很容易受到重发和/或底层攻击的攻击。你可以阅读更多关于它在这些网页:

  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/

总之,如果你并不需要一个字段,则它不应该在你的视图模型。您应该转换 - 将您的视图模型映射到域模型。虽然它可能很乏味,但它使您的应用程序更安全。您可以使用库来帮助您进行Automapper等映射。

编辑:由于我原来的答案,我已经得出结论,处理这种类型的情况最简单的方法是让您的视图模型实现IValidatableObject接口,然后在验证方法内写入您的验证逻辑。它不会为您提供客户端验证,但它是完成基于自定义/方案验证的最有效和最干净的方式,无需编写自己的自定义过滤器。

你可以阅读更多关于它在这里:有时http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3

+0

这是一个视图模型而不是域模型。基本上这是一个局部视图,有多种类型的输入,用户可以从中选择。但是输入的数量和类型是可配置的。但是需要显示任何显示的输入。 – Mykroft

1

我已经使用方法,其中的形式略有变化基于特定的下拉或单选按钮选择。

内,您的操作方法,你检查你ModelState.IsValid可以这样做ModelState.Remove("Object.PropertyName")

前:属性名应该是一样的呈现给客户端的ID。用一个 ”。”对于任何下划线。

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

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