C# 在MVC4表单中生成所需的复杂类型属性

C# 在MVC4表单中生成所需的复杂类型属性,c#,validation,asp.net-mvc-4,C#,Validation,Asp.net Mvc 4,当我将[Required]属性粘贴到自定义类型的属性时,我不知道如何“自定义”该属性的规则。代码如下所示: public class MyProp { public Guid Id {get;set;} public string Target {get;set;} } public class MyType : IValidatableObject { public string Name {get;set;} public MyProp Value {get;

当我将
[Required]
属性粘贴到自定义类型的属性时,我不知道如何“自定义”该属性的规则。代码如下所示:

public class MyProp
{
    public Guid Id {get;set;}
    public string Target {get;set;}
}
public class MyType : IValidatableObject
{
    public string Name {get;set;}
    public MyProp Value {get;set;}

    private MyType()
    {
        this.Name = string.Empty;
        this.Value = new MyProp { Id = Guid.Empty, Target = string.Empty };
    }
    public MyType(Guid id) : this()
    {
        this.Value.Id = id;
        // Fill rest of data through magic
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if(this.Value.Id == Guid.Empty)
            yield return new ValidationResult("You must fill the property");
    }
}
结果视图显示字段(当然是空的)。用户只能通过单击字段并从列表中进行选择来输入数据(jquery对话框会处理这个问题,而且它已经起作用了)

IValidatableObject
接口听起来很有希望,但代码似乎从未被调用过

在控制器中,我只是在

[HttpPost]
public ActionResult MyAction(FormCollection data)
{
    if (!ModelState.IsValid) return View();
    // magic: handle data
}

我错过了什么?我可能误解了
IValidatableObject
接口用法?

您的控制器操作应该将视图模型作为参数,而不是弱类型的
FormCollection
,它与您的模型(及其验证规则)完全没有关系:

现在将调用默认模型绑定器,以便从请求绑定视图模型,并评估此模型中可能存在的任何验证逻辑

您如何期望您的代码ASP.NET MVC知道您正在使用这个
MyModel
类?您绝对没有在POST操作中使用它,因此您不能期望对它进行任何验证


一旦你开始使用视图模型,你应该忘记弱类型的集合,比如
FormCollection
,开始使用那些视图模型。

也许这可以帮助你:我忘记了代码中的控制器部分,修正了问题。目前正在尝试实现链接帖子的想法。
MyModel
还包含按预期验证的
string
属性,非基类型的行为是否有所不同?我不太明白你的意思。顺便说一句,您不应该将数据注释属性(例如
[必需的]
)与
IValidatableObject
实现混为一谈。这些是相互排斥的。您应该决定使用这两种验证方法中的哪一种。这只是一个附带的问题/备注,但使用IValidatableObject是否可以更好地进行自定义javascript验证?我记得您在StackOverflow上回答了关于jquery.validation的问题。js@Silvermind,没有
IValidatableObject
与客户端javascript验证完全不起作用。如果使用
IValidatableObject
,则不会进行任何javascript验证。你必须把所有的东西都写下来。啊,我的错。谢谢你的澄清。
[HttpPost]
public ActionResult MyAction(FormCollection data)
{
    if (!ModelState.IsValid) return View();
    // magic: handle data
}
[HttpPost]
public ActionResult MyAction(MyModel model)
{
    if (!ModelState.IsValid) 
    {
        return View();
    }

    // magic: handle model
}