ビューモデルの階層を持つ複雑なフォームがあり、コントローラーにすべてのアクションのハンドラーが含まれないようにコードを構造化する方法を考えています。
簡単な例を次に示します: 対応する ViewModel を使用:
public class MyPageViewModel
{
public List<TabViewModel> Tabs {get; set; }
public CustomerViewModel Customer;
}
public class TabViewModel
{
public string DisplayLabel { get; set; }
public bool Selected { get; set; }
}
class CustomerViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Address> Addresses { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
ページの各部分のレンダリングを個別のコンポーネントに分割する方法を知っています。モデルの各部分に個別のビューを使用@Html.EditorFor
し@Html.DisplayFor
ています (上の図の赤い四角形で示されています)。これは非常にうまく機能します。ViewModel の一部 (TabViewModel
クラスなど) は、他のページでも再利用できます。
イベント処理ロジックに問題があります。このページで実行できるアクションはほとんどありません (青い背景で示されています)。1 つの可能性は、複数の FORM タグを使用することです。それぞれが上の図の 1 つの赤い四角形です。各フォームには異なるアクション URL があり、異なるコントローラーによって処理されます。しかし、このアプローチを使用すると、同じデータが失われる可能性があります。たとえば、ユーザーが First Name を変更してから [Remove Address] ボタンをクリックすると、First Name はサーバーに POST されず、変更は失われます。
これにより、ページ全体に対して 1 つのフォームが残ります。これは、すべてのアクションが単一のコントローラ クラスによって処理される必要があることを意味します。次の理由から、私はこのアプローチが本当に好きではありません。
- すべてのボタンのアクション処理コードを含む大きくて太ったコントローラーになってしまいます
- または、コントローラー内に大きな switch ステートメントを用意します。これは、アクションを識別し、アクションを処理する方法を知っている別のクラスを見つけ、それに処理を委譲します (うん! これは、Windows メッセージのイベント処理コードを1990年代 – WindowProc)
ビューから別のコントローラーを呼び出すことができる Html.ActionFor について読んだことがありますが、これも良いアプローチではないと思います (ビューがレンダリングされている間に発生しますが、これは問題ありません)。
要約すると、もう一度質問があります。複雑なビューモデルのさまざまな部分からトリガーされたアクション/イベントを、コントローラーで混乱しないように処理する方法はありますか? 実際のアプリケーションのベスト プラクティスは何ですか (Visual Studio のスキャフォールディングによって生成される 101 の CRUD の例ではありません)。
更新:これは単純化された例にすぎないことに注意してください。実際には、ビュー モデルははるかに複雑であり、実行できるアクションはさらに多くあります。ASP.NET MVC アプリケーションでコントローラー内のコードを構造化する (または別のクラスに移動する) ための一般的なアプローチについて質問しています。Web フォームはユーザー コントロールを提供し、ビュー パーツ (ASCX) とイベント ハンドラーの両方をカプセル化することができました。MVC にはビューをカプセル化するための優れたソリューションがあり、ロジック/イベント ハンドラーを構造化する正しい方法を見つけようとしています。