2012-01-24 11 views
0

私は、ASP MVCで書かれたかなり簡単なデータ監査Webアプリケーションを持っています。HTMLヘルパーを使用してコードの複製を減らす

  1. エージェントビュー - 情報の検証者が記入したフォーム。このビューのフォーム上の各フィールドには、サブフィールドが3つあります。

    a。元の値 - 呼び出し前のデータベースからの値

    b。新しい価値 - 元の人と異なる場合、人が電話で提供した価値。

    c。アクション - 何が起こったかの一般的な表示

  2. QCビュー - エージェントビューで実行された作業をレビューする人が入力したフォーム。このビューのフォームの各フィールドには、5つのサブフィールドがあります。

    a。元の値 - 上記と同じ

    b。エージェント値 - エージェントが上の1bで提供した値。

    c。 QC値 - エージェントによって指定された値が正しくない場合、修正された「新しい値」。

    d。エージェントアクション - 上記と同じですが、このビューでの読み取りのみを除きます。

    e。 QCアクション - エージェントによって不適切に選択された場合、訂正された「新しいアクション」。

2つのビューの唯一の違いは、使用可能なサブフィールドです。私はページの全体的な構造が同一であり、HTMLフィールドヘルパーを使ってサブフィールドの違いを処理するので、両方のビューを表現するために単一のビューを使用できるようにしたい。私はこれまで持っています(現在はいえ分離することができ、同じクラスで)ヘルパーの2はっきりと別のシリーズ:フルネームのような第三の実装は、複数のデータで構成される、より複雑なフィールドを扱う

// Agent controls 
public static MvcHtmlString AuditControl(this HtmlHelper htmlHelper, string id, string fieldLabel, MvcHtmlString editControl, string cssClass) 
public static MvcHtmlString AuditControl(this HtmlHelper htmlHelper, string id, string fieldLabel, string editControl, string cssClass) 
public static MvcHtmlString AuditControl<COMPLEX>(this HtmlHelper htmlHelper, string id, string fieldLabel, string cssClass) where COMPLEX : AbstractComplex, new() 

// QC controls 
public static MvcHtmlString ReviewControl(this HtmlHelper htmlHelper, string id, string fieldLabel, MvcHtmlString editControl, string cssClass) 
public static MvcHtmlString ReviewControl(this HtmlHelper htmlHelper, string id, string fieldLabel, string editControl, string cssClass) 
public static MvcHtmlString ReviewControl<COMPLEX>(this HtmlHelper htmlHelper, string id, string fieldLabel, string cssClass) where COMPLEX : AbstractComplex, new() 

( 、アドレスなど)。

私が考えてきた解決策の1つは、さまざまな種類のコントロールを共通のインターフェイスを実装する異なるクラスに分けて、より一般的なHTMLヘルパーに型パラメーターとして渡すことです。私はこれがうまくいくと思いますが、どういうわけかViewを描画するためにどの実装を使うべきかをViewに伝える必要があります。ViewとControllerの間の線がぼやけているように見えます。

明白なような魅力的ではないアプローチの1つは、コントローラからの管理フラグを渡すことです。このフラグは、汎用(論理型ではないタイプの汎用)ファクトリヘルパーによって使用され、使用する方法。これはモデルとビューを別々に保ちますが、HTMLヘルパーは単なるHTMLの構築以上の責任を負うことになるので、汚いと感じます。

これは、MVCによって設計された懸念の分離を破るのに妥当な状況ですか、より適切な解決策がありますか?

+0

あなたの解決策はあまりにも複雑に聞こえます。どのバージョンのASP.NET MVCを使用していますか? – SoWeLie

+0

@ SoWeLie - MVC 3を使用しています。 –

答えて

3

あなたはMVC3を使用しているので、私はサブフィールドの子アクションを使用することをお勧めします:

http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx

子の行動は、あなたのビューの内部コントローラのアクションを実行することができ、これは次のようになりますはるかにクリーンなアプローチ。

+0

これはどのように状態をヘルパーに渡すのと違うのですか? –

+0

子アクションを使用すると、別のビューをレンダリングすることができます。ヘルパーを使用すると、C#関数の内部でマークアップを連結する必要があります。 – SoWeLie

+0

良い点。私はそれを撃つだろう。 –

0

@SoWeLieが提供するアドバイスをかなり簡単に実装することができました。可能な制御プロパティのスーパーセットと、異なるコントロールセット(Audit用とReview用)のそれぞれについて描画される新しいビューのスーパーセットを格納するための新しいモデルの作成が必要でした。私は、一般的なヘルパーが、この中で動作するように取得する方法を見つけ出すことができませんでした

public ActionResult DrawControl(string id, ...) 
{ 
    // FieldControl being the name of my Model 
    var viewModel = new FieldControl() { ID = id, ... }; 
    if (shouldRenderAudit) 
     return PartialView("AuditControl", viewModel); 
    else 
     return PartialView("ReviewControl", viewModel); 

@Html.RenderAction("DrawControl", new { id = "ID" ... }) 
// Repeated for all of the overloads of DrawControl 

、各コントローラのアクションのようなものが含まれていました。それに伴う問題は、結果の表示APIは醜いでしたさらに、明らかなコードの重複を減らして、すぐにこれを削除したいと思っていました。

@functions { 
    public string DrawControl(string id, ...) 
    { 
     return Html.Render("DrawControl", new { id = "ID" }); 
    } 
    // Repeated for all of the overloads of DrawControl 
} 

@DrawControl("ID", ...) 

同じコントローラアクションで。この問題(ビューには機能が全くないという事実を無視して)は、@functionsブロックを使用する利点を望むビューに含める必要がありました(現在のところ2のみですが、私の前任者がこれでやっていることを知っている)。私はすぐに、再びヘルパーを戻すには、この時間(一般ビュー、モデル、およびコントローラの変更を維持する)、コードを再加工し、最終的にはこれで終わった:

ビュー:

@(Html.DrawComplexControl<ProviderName>("id", ...)) 
@Html.DrawSimpleControl("id", ...) 

コントローラ:

// One common action that is used to determine which control should be drawn 
public ActionResult DrawControl(FieldControl model) 
{ 
    if (shouldRenderAudit) 
     return PartialView("AuditControl", model); 
    else 
     return PartialView("ReviewControl", model); 
} 

ヘルパー:もちろん

public static MvcHtmlString DrawControl(this HtmlHelper htmlHelper, string id, ...) 
{ 
    var model = new FieldControl() { ID = id, ... }; 

    return htmlHelper.Action("DrawControl", model); 
} 

public static MvcHtmlString DrawSimpleControl(this HtmlHelper htmlHelper, string id, ...) 
{ 
    return DrawSimpleControl(htmlHelper, id, ...); 
} 
public static MvcHtmlString DrawSimpleControl(this HtmlHelper htmlHelper, string id, ...) 
{ 
    // Set some defaults to simplify the API 
    return DrawControl(htmlHelper, id, ...); 
} 

public static MvcHtmlString DrawComplexControl<T>(this HtmlHelper htmlHelper, string id, ...) where T : AbstractComplex, new() 
{ 
    // Build the required controls based on `T` 

    return DrawControl(htmlHelper, id, ...); 
} 

OT半ダース程度ありました状況を助けるために示されたものの間の彼女の反復、およびそれらのどれもは必要な程度までしなかった。私はまだ改善がなされていると確信していますが、これはこれまでのところあります。

このようにすると、Viewを実装する上で気にせずに使用できる非常に単純なAPIが提供され、マイナーな変更だけで既存のAPIのすべての要件を満たすことができます少なくとも)。これが結果として意図されたものなのかどうかは分かりませんが、機能的であり、必要なシンプルさを提供します。

私の頭痛は、将来他の人に役立つことを願っています。

関連する問題