2011-12-02 15 views
14

のために真であることからModelMetadata.IsRequiredを無効にするにはどうすれば単純なモデルを持っています。したがって、検証のためにGlobal.asaxにDataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = falseを設定してください。は常にnull非許容値型

私もモデルが必要とされている場合はtrueまたはfalse出力する簡単なHTMLヘルパーを持っている:

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()); 
    } 
} 

私も私の問題を披露するビューを書いた:

@model MvcApplication10.Models.Sample 

A: @Html.IsRequired(m => m.A), B: @Html.IsRequired(m => m.B) 

私が期待しているだろうこれはA: false, B: trueを印刷しますが、実際にはA: true, B: trueを出力します。

この印刷を期待通りの結果にする方法はありますか?私が明示的にRequiredAttributeを設定していなくても、IsRequiredは常に真を返すようです。 docsは、デフォルトではヌル値を持たない値の型に対して真であると述べています。検証と同様に、これをfalseに設定する簡単な方法がないのはなぜですか?

EDIT:私はあなたがMVCのバグに直面していると思います

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; 
    } 
} 
+2

'DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false'のは今自動的にnull非許容値は' RequiredAttribute'を添加しない期待される効果を持っていませんタイプ。 – Cocowalla

答えて

3

:私はこのようなカスタムプロバイダを書くことができますが、この周りに「簡単」な方法があった場合、私は思っていました。常にその状況にトリガするに必要な、どんなあなたが

DataAnnotationsModelValidatorProvider 
    .AddImplicitRequiredAttributeForValueTypes = false; 

を使用する場合でも、このすでにhereを議論しないとhereを報告しました。この例はさらに進んで、暗黙的に要求されたトリガーがIValidatableObjectの実行を妨げないことを示しています。 2番目のリンクからデモを実行すると、必要に応じてケースを再現することができます。私はいくつかの中でこの問題を抱えている

public bool? A { get; set; } 
+0

プロパティを 'bool? 'に設定すると、ブール値を必要とする' CheckBoxFor'のようなビルトインのHTMLヘルパーを使うことができません。はい - 私自身のHTMLヘルパーを書くことができましたが、私がOPでやったようなモデルメタデータプロバイダを書く方が理にかなっているかどうか不思議です。 – TheCloudlessSky

+0

期待どおりの動作であり、MVCが現在このように動作していることを考慮すると、カスタムプロバイダが唯一のオプションだと思います。 – Joao

+0

'A'プロパティは検証をトリガしていますか? 'IsRequired'が' true'であるということは、プロパティが有効でないことを意味しません。 – Joao

0

とにかく、これはあなたがA is obviously not requiredは、それがNULL可能であることを言うと同じであることを言っている場合ので、解決するのは簡単ですので、ちょうどそのように行いますこのような簡単な修正を実装しました

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

ご存知のように、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)) 
{ ... } 
+0

これは素晴らしいです。それが誰にでも役立つ場合は、フィールドが必要な場合は、フィールドlableの前に適切な "*" html文字列を配置するラベル拡張メソッドを組み込む必要がありました。それはMVC5で、私はまだValueTypesが真を返すいくつかの問題を抱えていました。多くのフォームフィールド(49)がありますので、メタデータを検索するためにリフレクションを使用するために上記を変更しました。目的のプロパティを見つけるためのコンテナタイプ:metaData.ModelType.IsValueType && metadata.ContainerType.GetProperty(metadata.PropertyName).GetCustomAttributes typeof(RequiredAttribute)、false).Any()。 – bphillips

1

以下は、[必須]かどうかによって真または偽を返します。

typeof(<YourModel>).GetProperty(<PropertyName>).GetCustomAttributes(typeof(RequiredAttribute), false).Any()

3

私があったようにあなたは、EditorTemplateで作業している場合は、一歩必要がありますするために、あなたはモデルのメタデータからコンテナタイプを取得する必要があります

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

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

を特定のプロパティの属性を確認してください。それ以外の場合は、の属性ではなく、プロパティのデータ型がの属性をチェックしているだけです。あなたはそれがあまりにもNULL可能タイプのために仕事をしたい場合は

+0

あなたは私の一日を保存します:D – senzacionale

+0

これはMVC5.2でも機能しました。 @ ViewData.ModelMetadata.IsRequired –

0

:MVC5は、単に設定で

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; 
} 
関連する問題