しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC の ModelMetadata は奥が深い

ASP.NET MVC ではモデルクラスに設定されたデータアノテーション属性は、使用時に ModelMetadata へキャッシュされる形になってます。

ModelMetadata クラス (System.Web.Mvc)

データアノテーションを読み込んでいるのは DataAnnotationsModelMetadataProvider クラスです。ソースを読むといろいろな苦労が分かってきます。

どんな属性を認識して読み込んでいるかは Brad Wilson 氏の記事でわかりやすく説明されています。ASP.NET MVC 2 の時の記事ですが MVC 3 でも変わっていません。

Brad Wilson: ASP.NET MVC 2 Templates, Part 2: ModelMetadata

例を挙げると、デフォルトではフォームに空文字列が入力された場合にはモデルバインダによって null に変換されますが、DisplayFormat 属性で ConvertEmptyStringToNull プロパティに false をセットすると空文字列のまま取得できるようになります。

// 自動的に null へ変換しない
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Name { get; set; }

想像以上に属性で設定できる項目は多いです。そして ModelMetadata を使うと、ラムダ式からモデルの値を取得できます。

// ラムダ式から ModelMetadata を取得する
var metadata = ModelMetadata.FromLambdaExpression(model => model.Name, ViewData);

// Model プロパティからモデルの値を取得
var model = (string)metadata.Model;

Model プロパティは object 型なのでキャストしてください。Model の型は ModelType に入っています。