Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何禁用ModelMetadata.IsRequired,使其对于不可为null的值类型始终为true_C#_.net_Asp.net Mvc_Asp.net Mvc 3 - Fatal编程技术网

C# 如何禁用ModelMetadata.IsRequired,使其对于不可为null的值类型始终为true

C# 如何禁用ModelMetadata.IsRequired,使其对于不可为null的值类型始终为true,c#,.net,asp.net-mvc,asp.net-mvc-3,C#,.net,Asp.net Mvc,Asp.net Mvc 3,我有一个简单的模型: public class Sample { public bool A { get; set; } [Required] public bool B { get; set; } } 这显然不是必需的。因此,为了验证,我们在Global.asax中设置了DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes=false 我还有一个简单的html助

我有一个简单的模型:

public class Sample
{
    public bool A { get; set; }

    [Required]
    public bool B { get; set; }
}
这显然不是必需的。因此,为了验证,我们在Global.asax中设置了
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes=false

我还有一个简单的html助手,如果需要模型,它可以打印true或false:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString IsRequired<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);        
        return new MvcHtmlString(metadata.IsRequired.ToString());
    }
} 
我本以为它会打印
A:false,B:true
,但实际上它会打印
A:true,B:true

有没有办法让这张照片成为我的预期结果
IsRequired
似乎总是返回true,即使我没有明确设置
required属性
。默认情况下,对于不可为null的值类型为true的状态。为什么没有简单的方法可以像验证一样将其设置为false

编辑:我可以编写这样的自定义提供程序,但我想知道是否有一种“简单”的方法:

public class ExtendedDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    private static bool addImplicitRequiredAttributeForValueTypes = false;

    public static bool AddImplicitRequiredAttributeForValueTypes
    {
        get
        {
            return addImplicitRequiredAttributeForValueTypes;
        }
        set
        {
            addImplicitRequiredAttributeForValueTypes = value;
        }
    }

    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var result = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        if (!AddImplicitRequiredAttributeForValueTypes && modelType.IsValueType && !attributes.OfType<RequiredAttribute>().Any())
        {
            result.IsRequired = false;
        }

        return result;
    }
}
公共类ExtendedDataAnnotationsModelMetadataProvider:DataAnnotationsModelMetadataProvider
{
私有静态bool addImplicitRequiredAttributeForValueTypes=false;
公共静态bool AddImplicitRequiredAttributeForValueTypes
{
得到
{
返回addImplicitRequiredAttributeForValueTypes;
}
设置
{
addImplicitRequiredAttributeForValueTypes=值;
}
}
受保护的重写ModelMetadata CreateMatadata(IEnumerable属性、类型containerType、Func modelAccessor、类型modelType、字符串propertyName)
{
var result=base.CreateMetadata(属性、containerType、modelAccessor、modelType、propertyName);
如果(!AddImplicitRequiredAttributeForValueTypes&&modelType.IsValueType&&attributes.OfType().Any())
{
result.IsRequired=false;
}
返回结果;
}
}

我猜您正面临一个MVC错误。无论发生什么情况,即使您使用

DataAnnotationsModelValidatorProvider
    .AddImplicitRequiredAttributeForValueTypes = false;
这已经得到讨论和报告。本例进一步说明,当隐式required触发时,它不会阻止执行
IValidatableObject
。如果您从第二个链接运行演示,您可以复制您的案例,需要的地方总是正确的

无论如何,这很容易解决,因为如果你说
A显然不是必需的
与说它可以为null是一样的,那么就这样做:

public bool? A { get; set; }

我在好几个地方遇到过这个问题,并且实现了一个类似这样的简单修复

if (metadata.ModelType == typeof(System.Boolean))
{
    metadata.IsRequired = false;
}

正如您所指出的,ValueTypes将默认为true。要解决这个问题,如果类型是
ValueType
,则可以检查
RequiredAttribute

ModelMetadata metaData = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, html.ViewData);

if ((metaData.ModelType.IsValueType && metaData.ModelType.GetCustomAttributes(typeof(RequiredAttribute), false).Any()) ||
    (!metaData.ModelType.IsValueType && metaData.IsRequired))
{ ... }
modelmatadata=modelmatadata.FromLambdaExpression(表达式,html.ViewData);
if((metaData.ModelType.IsValueType&&metaData.ModelType.GetCustomAttributes(typeof(RequiredAttribute),false)。Any())||
(!metaData.ModelType.IsValueType&&metaData.IsRequired))
{ ... }

根据您是否有[必需]选项,以下选项将返回true或false


typeof().GetProperty().GetCustomAttributes(typeof(RequiredAttribute),false)。Any()

如果您像我一样在EditorTemplate中工作,您还需要一个步骤:

var metaData = ModelMetadata.FromLambdaExpression(Model => Model, ViewData);

var required = metaData.ContainerType.GetProperty(metaData.PropertyName).GetCustomAttributes(typeof (RequiredAttribute), false).Any();

您需要从模型元数据中获取容器类型,以便检查特定属性的属性;否则,您只需检查属性的数据类型的属性,而不是属性的属性,,如果您希望它也适用于可为空的类型:

private static bool RequiredAttrExists(ModelMetadata metaData)
{
    if(!metaData.ModelType.IsValueType && metaData.IsRequired)
        return true;
    else if (metaData.ModelType.IsValueType && metaData.ContainerType.GetProperty(metaData.PropertyName).GetCustomAttributes(typeof(RequiredAttribute), false).Any())
        return true;
    return false;
}

将属性设置为
bool?
意味着我不能使用需要布尔值的内置html帮助程序,如
CheckBoxFor
。是的-我可以编写自己的html帮助程序,但我仍然很好奇,是否像我在OP中那样编写模型元数据提供程序更有意义。这是您的预期行为,考虑到MVC目前的行为方式,我猜自定义提供程序是您唯一的选择。
属性是否触发验证?因为
IsRequired
true
并不意味着属性无效。不,它不是。我不需要这个来验证,但对于仅用于显示的自定义HTML帮助程序,只需在MVC5中简单设置
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes=false
就不会自动为不可为空的值类型添加
RequiredAttribute
。这真是太棒了。如果它对任何人都有帮助,我必须组合一个标签扩展方法,如果字段是必需的,则在字段标签前面放置适当的“*”html字符串。它是MVC5,我仍然对ValueTypes返回true存在一些问题。有很多表单字段(49),所以我修改了上面的内容,使用反射来搜索metadata.ContainerType以定位所需的属性:metadata.ModelType.IsValueType&&metadata.ContainerType.GetProperty(metadata.PropertyName).GetCustomAttributes(typeof(RequiredAttribute),false).Any()。这在MVC5.2上也起作用@ViewData.ModelMetadata.IsRequired
private static bool RequiredAttrExists(ModelMetadata metaData)
{
    if(!metaData.ModelType.IsValueType && metaData.IsRequired)
        return true;
    else if (metaData.ModelType.IsValueType && metaData.ContainerType.GetProperty(metaData.PropertyName).GetCustomAttributes(typeof(RequiredAttribute), false).Any())
        return true;
    return false;
}