しばやん雑記

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

ASP.NET MVC でバリデーションを良い感じに扱う

ASP.NET MVC はバリデーションの結果としてのエラーメッセージ出力が実装されていますが、これがいまいち自由度が低くて実際にはあまり使えないです。

なので、良い感じにバリデーションを扱うためにヘルパーを作りました。

public static class ValidationHelpers
{
    public static bool IsValidationError(this HtmlHelper htmlHelper)
    {
        return !htmlHelper.ViewData.ModelState.IsValid;
    }

    public static IEnumerable<string> GetValidationMessages(this HtmlHelper htmlHelper)
    {
        return htmlHelper.ViewData.ModelState.SelectMany(p => p.Value.Errors).Select(p => p.ErrorMessage);
    }
}

エラーがあったか判定するヘルパーと、エラーメッセージだけを出力するヘルパーです。何かメソッド名がアレなのはスルーで。

この 2 つのヘルパーを使うとエラーの出力を自由にカスタマイズすることが出来るわけです。

@if (Html.IsValidationError())
{
    <ul>
    foreach (var errorMessage in Html.GetValidationMessages())
    {
        <li><i class="icon-error"></i>@errorMessage</li>
    }
    </ul>
}

ここで ASP.NET MVC でのバリデーションについておさらい。

ASP.NET MVC ではモデルに対するバリデーションの結果は ModelState プロパティに格納されています。こいつはコレクションになっていて、殆どの場合はモデルのプロパティ名のキーに対して ModelState クラスのインスタンスが格納されてます。

更に ModelState クラスは Errors プロパティを持っていて、こいつが実際にエラーメッセージを保持しています。場所によって取り方が若干異なるので注意です。

// コントローラでは Controller.ModelState を持ってるので直接とれる
if (ModelState.IsValid) { }

// ビューでは ViewData を経由して取る
if (ViewData.ModelState.IsValid) { }

// ヘルパーでは HtmlHelper を経由して取る
if (htmlHelper.ViewData.ModelState.IsValid) { }

モデルのバリデーション結果が集約されているので、様々な場所から自由に弄ることが出来るので非常に便利ですね。