22

編集:これ以外のMVC3ソリューション(存在する場合)を探しているため、報奨金を追加しました:

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;


'Address'モデルに読み取り専用プロパティがあります'CityStateZip'

これは、米国の住所から都市、州、zipを取得するための便利な方法です。国が米国でない場合は例外がスローされます(発信者が最初にチェックすることになっています)。

    public string CityStateZip
    {
        get
        {
            if (IsUSA == false)
            {
                throw new ApplicationException("CityStateZip not valid for international addresses!");
            }

            return (City + ", " + StateCd + " " + ZipOrPostal).Trim().Trim(new char[] {','});
        }
    }

これは私のモデルの一部なので、バインドされます。ASP.NET MVC2 RC2より前は、このフィールドによってデータバインディング中に問題が発生することはありませんでした。私はそれについて本当に考えたことさえありませんでした-結局のところ、それは読み取り専用です。

2010年1月のRC2リリースでは、データバインディング中にエラーが発生しますが、デフォルトのモデルバインダーがこの値をチェックするように見えるためです(読み取り専用ですが)。

このエラーがトリガーされるのは、「base.OnModelUpdated」行です。

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

モデルバインダーへの直前の変更により、明らかにこの動作の変更が発生しましたが、その結果が何であるか、またはこれがバグであるかどうかはまだよくわかりません。私はこれをMVCチームに渡しますが、その間に他の誰かがこのプロパティのバインドを防ぐ方法について何か提案があれば興味があります。

この記事は変更について読む価値がありますが、読み取り専用プロパティについてはまったく触れていません(私が期待していることではありません)。問題(ある場合)は、この状況よりも広範囲である可能性があります-もしあれば、逆効果についてはよくわかりません!

ASP.NETMVCでの入力検証とモデル検証


@haackedによって要求されたように、ここにスタックトレースがあります:

これは、任意のモデルに次の行を追加し、対応するアクションメソッドに投稿するだけで取得できます。この例では、可能な限り単純なモデルに追加しました。

 public string Foo { get { throw new Exception("bar"); } }

[TargetInvocationException:オブジェクト'Rolling_Razor_MVC.Models.ContactUsModel'のプロパティアクセサー'Foo'が次の例外をスローしました:'bar'] System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component)+390System.Web.Mvc。<>c__DisplayClassb。<GetPropertyValueAccessor>b__a()+18 System.Web.Mvc.ModelMetadata.get_Model()+22System.Web.Mvc。 ModelMetadata.get_RealModelType()+29System.Web.Mvc。<GetValidatorsImpl>d__0.MoveNext()+38System.Linq。<SelectManyIterator>d__14`2.MoveNext()+273System.Web.Mvc。<Validate>d__5。 MoveNext()+644 System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext、ModelBindingContext bindingContext)+92 System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext、ModelBindingContext bindingContext、Object model)+60System.Web.Mvc。 DefaultModelBinder.BindComplexModel(ControllerContext controllerContext、ModelBindingContext bindingContext)+1048 System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext、ModelBindingContext bindingContext)+280 System.Web.Mvc.Controller.TryUpdateModel(TModel model、String prefix、String [] includeProperties、String [] extractProperties、IValueProvider valueProvider)+449 System.Web.Mvc.Controller.TryUpdateModel(TModelモデル)+73

4

7 に答える 7

19

同様の問題が発生していると思います。詳細を投稿しました:

http://forums.asp.net/t/1523362.aspx


編集:MVCチームからの応答(上記のURLから):

これを調査し、検証システムが期待どおりに動作していると結論付けました。モデルの検証にはすべてのプロパティに対する検証の実行が含まれ、null許容でない値型のプロパティには暗黙の[必須]属性があるため、このプロパティを検証し、プロセスでそのゲッターを呼び出します。これは製品のV1からの重大な変更であると理解していますが、新しいモデル検証システムを正しく動作させる必要があります。

これを回避するためのいくつかのオプションがあります。これらのいずれかが機能するはずです:

  • Dateプロパティをプロパティではなくメソッドに変更します。このようにすると、MVCフレームワークでは無視されます。
  • プロパティタイプをDateTimeに変更しますか?DateTimeの代わりに。これにより、このプロパティから暗黙の[必須]が削除されます。
  • 静的DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypesフラグをクリアします。これにより、アプリケーション全体のnull許容でないすべての値型プロパティから暗黙の[必須]が削除されます。製品のV3に、「バインドしない、検証しない、このプロパティが存在しないふりをする」というシグナルを表示する属性を追加することを検討しています。

報告ありがとうございます!

于 2010-02-08T20:32:20.163 に答える
2

MVC3 でも同じ問題が発生します。

global.asax でこれを行うのが最善の方法だと思います(SevenCentralの回答から):

 DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

これにより、それらすべてが無効になります

于 2011-05-04T01:00:44.573 に答える
1

これは、私にとってバグのように全世界を探します。ModelBinder が読み取り専用プロパティをチェックする必要がある理由を完全に理解できません (技術的なこともあるかもしれませんが、私には理解できず、時間をかけたくありません)。

問題を回避するために、次のモデル メタ データ プロバイダーをソリューションに追加しました。

protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(IEnumerable<Attribute> attributes, Type containerType, Type modelType, string propertyName)
{
    var metadata = base.CreateMetadataPrototype(attributes, containerType, modelType, propertyName);

    if (metadata.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func<object> modelAccessor)
{
    var metadata = base.CreateMetadataFromPrototype(prototype, modelAccessor);

    if (prototype.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

また、以下を Global.asax.cs に追加する必要があります。

protected void Application_Start()
{
    ModelMetadataProviders.Current = new RESModelMetadataProvider();
    ModelBinders.Binders.Add(typeof(SmartDate), new SmartDateModelBinder());

    ...
}
于 2014-03-14T16:53:33.673 に答える
0

CityStateZipもちろん、変換できると思いGetCityStateZip()ますが、Silverlightのようなものに簡単にバインドすることはできません。これは、この問題が発生している他の人の一時的な修正に役立つ可能性があります。

于 2010-02-06T03:06:14.170 に答える
0

私はまったく同じ問題を抱えています!!

私の問題の詳細については、ASP.NET MVC 2.0 未使用のモデル プロパティが、製品をサーバーに投稿するときに呼び出されますか? を参照してください。

これは、プロパティが予期せず呼び出されることを前提としてプロパティをプログラムする必要があることを意味しますか (それが依存するプロパティが設定/初期化される前など)... もしそうなら、これはプログラミング慣行の変更を表し、私は続行する方法を知りたいです。

その間、問題を取り除く単純な「if」チェックがあります。

于 2010-05-06T13:18:20.263 に答える
0

私は同様の問題を抱えていました。フォームがコントローラーにポストバックされたときに、検証されるとは思わなかったフィールドがエラーを受け取っていました。いくつかのグーグルの後名前の競合が問題を引き起こします。

ポストバック変数クラスに競合するプロパティ名があるとは思いませんでしたが、エラーを受け取ったプロパティの名前を変更すると問題が解決しました。

于 2012-05-10T14:51:15.077 に答える
0

同じ問題が MVC 5.2.3 にも存在し、検証コードが問題を引き起こしているわけではありません。はDefaultModelBinder、getter が読み取り専用プロパティであっても、それらのプロパティに一致する要求データがコントローラーに渡されていなくても、検証コードの外部で getter を呼び出します。

より詳細な説明と私の完全な解決策については、https ://stackoverflow.com/a/54431404/10987278 を参照してください。

そのソリューションが MVC 3 で動作するようにリファクタリングできるかどうかはわかりませんが、この質問に出くわした MVC の新しいバージョンで同じ問題に苦しんでいる他の人を助けることができれば幸いです。

于 2019-01-30T02:09:35.747 に答える