1

私は MVC3 アプリケーションを開発しており、ユーザーがドキュメントのメタ情報を編集できるページ (まあ、ビュー) を持っています (古典的な@Html.BeginForm使用法)。一般的なドキュメントの場合、入力する標準フィールドがユーザーに表示されますが、ドロップダウン リストを介してドキュメントのタイプを指定できます。これは、ajax 呼び出しを介して、edit-document-form に新しいフィールドをロードします。ユーザーが完成したフォームを送信すると、最後に、コントローラーはすべての標準フィールドに加えて、選択されたドキュメントのタイプに固有として読み込まれたすべてのフィールドを読み取る必要があります。

質問は、コントローラーでこの余分なフィールドをすべて処理するにはどうすればよいですか? class と、、などDocumentのその他のクラス extendsinf があり、それぞれが特定のプロパティ (およびフォームにロードされるこのフィールド) を持っているとします。コントローラーにアクションを記述するにはどうすればよいでしょうか?DocumentContract : DocumentInvoice : DocumentComplaint : Document

私は次のようなものを使用することを考えました(簡潔にするために、すべての変換、検証などを省略します)

[HttpPost]
public ActionResult Save(dynamic doc)
{
    int docType = doc.type;
    switch (docType)
    {
        case 1:
            var invoice = new Invoice(doc);
            invoice.amount = Request.Form["amount_field"];
            invoice.code = Request.Form["code_field"];
            //and so forth for every specific property of Invoice
            Repository.Save(invoice);
            break;
        case 2:
            var contract = new Contract(doc);
            contract.fromDate = Request.Form["fromDate_field"];
            contract.toDate = Request.Form["toDate_field"];
            //and so forth for every specific property of Contract
            Repository.Save(contract);
            break;
        ..... // and so forth for any document types

        default:
            break;
    }
}

しかし、それは私には非常に汚いアプローチのようです。これを達成する方法について、より良いアイデアはありますか?このようなシナリオにアプローチするには、私が何も知らないパターンがあるのか​​もしれません。

アップデート

2番目のアイデアが頭に浮かびます。Documentロブ・ケントの答えにコメントした後、次のようなプロパティを持つクラスを1つだけ持つ、別のアプローチを取ることができると思いました

public IEnumerable<Field> Tipologie { get; set; } 

どこ

public class Field
{
    public int IdField { get; set; }
    public String Label { get; set; }
    public String Value { get; set; }
    public FieldType ValueType { get; set; }
    public List<String> PossibleValues { get; set; } // needed for ENUMERATION type
}

public enum FieldType 
{
    STRING, INT, DECIMAL, DATE, ENUMERATION
}

これはより良いアプローチですか?この場合、私は次のようなアクションメソッドを持つことができます

[HttpPost]
public ActionResult Save(Document doc)

しかし、MVC エンジンにモデルへのバインディングを行わせるために、ビューにフィールドを作成する必要がありますか? 最初のアプローチで継承するクラスDocumentがおそらく実行時に生成されることを考えると、この 2 番目のアプローチを好むでしょうか?

4

1 に答える 1

0

サーバー上ですべてハードタイプされたままにするために、カスタム バインダーで抽象基本型を使用できます。これがどのように機能するかを確認するには、ここで私の回答を参照してください: MVC ジェネリック ビューモデル

新しいフィールド セットをロードするたびに、BindingType フォーム変数をハンドラーのインスタンス化された型に変更するという考え方です。カスタムバインダーは、送信時に正しいタイプを作成する責任があり、アクションでそれを評価できます。次に例を示します。

if (model is Contract) ...

それぞれ異なる署名で異なるアクションを設定できるかどうかはわかりません。たとえば、次のようになります。

public ActionResult Save(Contract contract) ...
public ActionResult Save(Invoice invoice) ...

Mvc はどのメソッドを呼び出すかを既に決定しているか、または最初に返される型を確認してから決定するため、それがうまくいかないことは確かです。

リンクされた例では、オーバーライドされた基本メンバーをチェックしていますが、それが問題にならない場合は、正しい型を作成するだけで済みます。

于 2012-05-08T16:27:01.393 に答える