2

我有一个名为Foo的模型,它有一个名为MyProp的Bar类型的属性。当我将此模型发布到控制器时,我希望模型绑定器验证MyProp,因为它具有所需的属性,就像它使用字符串一样。我需要它在 Bar 类中独立或作为一个单独的类。我曾尝试在Bar类上使用 IValidatableObject ,但似乎无法检查Foo类是否在MyProp上具有Required属性?所以现在我别无选择,需要一些帮助。下面是我的问题的一些示例代码。

public class Foo {
    [Required]
    public Bar MyProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    public string Name { get; set; }
}
4

3 回答 3

2

这是我的问题的一种解决方案,我可以使用内置的 required 属性并仍然获得自定义行为。这只是一些概念验证代码。

该模型:

public class Page : IPageModel {
    [Display(Name = "Page", Prompt = "Specify page name...")]
    [Required(ErrorMessage = "You must specify a page name")]
    public PageReference PageReference { get; set; }
}

模型粘合剂:

public class PageModelBinder : DefaultModelBinder {
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(bindingContext.ModelType)) {
            var attributes = property.Attributes;
            if (attributes.Count == 0) continue;
            foreach (var attribute in attributes) {
                if (attribute.GetType().BaseType == typeof(ValidationAttribute) && property.PropertyType == typeof(PageReference)) {
                    var pageReference = bindingContext.ModelType.GetProperty(property.Name).GetValue(bindingContext.Model, null) as PageReference;
                    Type attrType = attribute.GetType();
                    if (attrType == typeof (RequiredAttribute) && string.IsNullOrEmpty(pageReference.Name)) {
                        bindingContext.ModelState.AddModelError(property.Name,
                            ((RequiredAttribute) attribute).ErrorMessage);
                    }
                }
            }
        }
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

模型绑定器提供程序:

public class InheritanceAwareModelBinderProvider : Dictionary<Type, IModelBinder>, IModelBinderProvider {
    public IModelBinder GetBinder(Type modelType) {
        var binders = from binder in this
                      where binder.Key.IsAssignableFrom(modelType)
                      select binder.Value;

        return binders.FirstOrDefault();
    }
}

最后是 global.asax 注册:

var binderProvider = new InheritanceAwareModelBinderProvider {
    {
        typeof (IPageModel), new PageModelBinder() }
    };
ModelBinderProviders.BinderProviders.Add(binderProvider);

结果:http ://cl.ly/IjCS

那么您如何看待这个解决方案?

于 2012-08-13T19:36:42.623 回答
0

问题是没有调用 html 字段MyProp,并且 MVC 不会对此属性进行任何验证。

实现目标的一种方法BarBar'sFoo. 您可以使用AutoMapper将管道代码最小化。

另一种解决方案是编写一个自定义验证属性来验证null值并使用它来代替Required属性。

于 2012-08-12T22:57:15.440 回答
0

解决方案 1

而不是使用[Required],尝试自定义ValidationAttribute

public class Foo {
    [RequiredBar]
    public Bar MyProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class RequiredBar : ValidationAttribute {

    public override bool IsValid(object value)
    {
        Bar bar = (Bar)value;

        // validate. For example
        if (bar == null)
        {
            return false;
        }

        return bar.Name != null;
    }
}

解决方案二:

简单的把RequiredBar对应的需要的属性放在上面,例如

public class Foo {
    //[RequiredBar]
    public Bar MyProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
}
于 2012-08-13T05:51:29.653 回答