0

だから私は自分のモデルにこの Fee 抽象クラスを持っています(データベースファーストを念頭に置いてEFによって生成されました)

public abstract partial class Fee
{    
    public int FeeId { get; set; }
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal StandardPrice { get; set; }   
}

さまざまな種類の料金をモデル化するために、他の多くのクラスに継承されます。たとえば、QuarterlyFee のようなものです。モデルには Customer クラスもあり、顧客はクラス CustomerRate によってモデル化されたカスタム料金を持つことができます。

顧客の詳細ページで、ユーザーがカスタム料金と標準料金を選択できるように、顧客の可能なすべての料金を表示しようとしています。

public class PossibleFee
{
    public int CustomerId { get; set; }
    public int FeeId { get; set; }
    public Boolean CustomRate { get; set; }
    public decimal CustomerPrice { get; set; }

    public virtual Customer Customer { get; set; }
    public virtual Fee Fee { get; set; }
}

そして、可能性のある料金 (ICollection PossibleFees) を保持するために Customer クラスにプロパティを追加し、そのプロパティを Controller メソッド (public ActionResult Details(int id = 0)) に入力し、後で EditorTemplate を作成します。ユーザーが編集できる製品に応じて、顧客に発生する可能性のあるすべての料金。

ただし、ポストバック時に [保存] ボタンを押すと、Default Model Binder がその仕事を行い、PossibleFee の ICollection を設定しようとし、PossibleFee ごとに同じ名前のプロパティを設定するために Fee オブジェクトを作成しようとします。

もちろん、 Fee は抽象的であるため機能しません。問題はかなり単純です。ポストバックでは必要ないため、ポストバックでそのプロパティを無視するように DefaultModelBinder に指示するにはどうすればよいですか?

クラスPossibleFeeのPossibleFeeのEditorTenplateで必要なフィールドを単純に再コピーしたり、Feeからabstractを削除したりできることはわかっています。しかし、モデルに触れずに DefaultModelBinder をニーズに合わせて調整できるかどうかを知りたいです。

EDIT 2:私の意見では、Yarxはよりクリーンなソリューションを提供しました。以下の2つの投稿を参照してください

編集: まあ、Carlos Corral Carvajal はほぼ正しく、ModelBinder がオブジェクトを作成しようとした後にメソッド SetProperty が呼び出されるため、代わりに BindProperty を上書きする必要がありました。

public class CustomModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
    {            
        if (propertyDescriptor.Attributes.Contains(new ModelBinderIgnoreOnPostback()))
        {
            return;
        }

        base.BindProperty(controllerContext, bindingContext,propertyDescriptor);
    }
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=false)]
public class ModelBinderIgnoreOnPostback : Attribute {}

誰かがそれを必要とする場合に備えて、カスタム属性を追加しました

4

2 に答える 2

1

私の提案は、ViewModel を分離して、Action ごとに別の ViewModel を持つようにすることです。情報を表示するためだけの ViewModel と、Post Back からの情報を受け入れるために使用される ViewModel を用意します。このような場合、PostBack でバインドするフィールドの大部分は、最初にデータを表示するために使用される ViewModel でも必要になるため、ViewModel を継承するのが最も簡単な方法です。たとえば、以下を参照してください。

public class PossibleFeeInputModel 
{
    public int CustomerId { get; set; }
    public int FeeId { get; set; }
    public Boolean CustomRate { get; set; }
    public decimal CustomerPrice { get; set; }

    public virtual Customer Customer { get; set; }
}

.

public class PossibleFeeViewModel : PossibleFeeInputModel
{
    public virtual Fee Fee { get; set; }
}

このように、PossibleFeeViewModel を使用してビューを表示しますが、PossibleFeeInputModel を使用して PostBack を受け入れるときにバインドします。

于 2013-04-05T13:21:19.170 に答える