1


2

クラス内のプロパティに書き込むクラスレベルの検証属性を実装する

検証属性でViewModelを装飾するASP.NET MVCサイトを構築しています。 検証したいことの1つは、フォームを介してユーザーが送信するアドレスがジオコーディング可能であることです。 そのために、私はすでにカスタムの ValidationAttribute`を作成し、 StreetAddress`プロパティに適用しています。

これは、2つのジオコーディングリクエストを実際に行っていることを除いて、すべて良好です。1つは検証用のViewModelで、もう1つは緯度と経度をデータベースに入力するためのコントローラーです。 不要なネットワークの使用と遅延を削減したいので、検証ジオコードからの結果をコントローラーに渡す必要があります。

このようなことを実現するには、ViewModelでLatitudeおよびLongitudeプロパティを作成する必要があると思います。 ビュー自体はこれらの2つのプロパティに影響しませんが、検証属性はジオコーディングの失敗を報告してビューを返すか、結果をプロパティに書き込みます。

検証属性が3つのプロパティにアクセスするには、クラス全体に適用する必要があります。 [ラインスルー] それを行う方法はまだわかりませんが、それがこの質問の目的です

更新: https://stackoverflow.com/questions/2783865/class-model-level-validation-as-opposed-to-property-level-asp-net-mvc-2-0/2784319#2784319 [この回答]、クラスレベルの検証属性を作成する方法を見つけました。 http://byatool.com/mvc/custom-data-annotations-with-mvc-how-to-check-multiple-properties-at-one-time/ [答えのリンク]は、内容の読み方も示しています。クラス内のプロパティの(リフレクション経由)。 ただし、プロパティに書き込む方法はまだわかりません。

'' '' '

私の質問

クラス全体に適用できる「ValidationAttribute」を作成するにはどうすればよいですか? 以下に、ViewModelに適用できる属性に変換するコードを投稿しました。

public class GeocodableAttribute : ValidationAttribute
    {
        public GeocodableAttribute() : base()
        {
            ErrorMessage = "We weren't able to find that location.";
        }
        public override bool IsValid(object value)
        {
            if (value == null) //we don't care if it's required or not.
            {
                return true;
            }
            var address = (string)value;
            var response = Geocoder.CallGeoWS(address.Trim());
            if(response.Status=="ZERO_RESULTS")
            {
                return false;
            }
            return true;
        }
    }

'' '' '

属性を*クラスの特定のプロパティに*書き込むようにするにはどうすればよいですか? この属性をViewModelに適用するとき、ジオコーディングの結果を2つのプロパティに書き込み、「trueを返す」ようにします。 それをどのように実装できますか?

*更新#2:*プロパティへの書き込み方法を見つけたと思います。 次のコードは機能しますか?

    private static void WritePropertyValue(object obj, string propertyName, object valueToWrite)
    {
        if (obj == null) return null;
        var type = obj.GetType();
        var propertyInfo = type.GetProperty(propertyName);
        if (propertyInfo == null) return null;
        propertyInfo.SetValue(obj, valueToWrite, null);
    }

'' '' '

これにより、他の属性/プロパティのクライアント側の検証が中断しますか? [[Required] [Range] `など、組み込みのValidationAttributesで装飾したViewModelに他のプロパティがあります。 クライアント側の検証も有効にしました。 新しい属性をViewModelクラス全体に適用すると、クライアント側の検証が完全に中断しますか、それとも他のプロパティの検証がクライアントで実行され、その後サーバーで合計検証が実行されますか?

1 Answer


1


1)プロパティレベルのValidationAttributeを介して外部クラスにアクセスすることはできません。

カスタムモデルバインダーを使用してこれを実現できます。 属性を検出し、それに応じて検証するだけです。

カスタムモデルバインダーの作成:http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx

2)いいえ 試しましたか?

これはほとんど重複しています。 だまされた投稿の質問と回答を確認します。 必要なことを実行できる別の手法、クラスレベルの検証が含まれている場合があります。