2012-01-24 75 views
0

我有一個相當簡單的數據審計Web應用程序用ASP MVC編寫,它有效地具有用於不同目的的相同模型的兩個視圖。使用HTML助手減少代碼重複

  1. 代理視圖 - 由驗證信息的人填寫的表格。此視圖中窗體上的每個字段有3個子字段:

    a。原始值 - 呼叫前數據庫的值

    b。新的價值 - 如果手機與原始手機不同,手機上提供的價值。

    c。操作 - 發生了什麼的一般指示

  2. QC視圖 - 由審查代理視圖中執行的工作的人填寫的表單。此視圖中窗體上的每個字段有5個子字段:

    a。原始值 - 與上述相同

    b。代理值 - 代理在上面1b中提供的值。

    c。 QC值 - 如果代理指定的值不正確,則更正的「新值」。

    d。業務代表操作 - 與上述內容相同,只能在此視圖中閱讀

    e。質檢行動 - 如果代理人選擇不當,則更正「新行動」。

兩個視圖之間的唯一區別是可用的子字段。我希望能夠使用單個視圖來表示兩個視圖,因爲頁面的整體結構是相同的,只需使用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() 

其中第三實現處理多個數據片段組成更復雜的領域(如全名,地址等)。

我考慮過的一種可能的解決方案是將不同類型的控件分成不同的類,它們實現一個通用接口,然後將它們作爲類型參數傳遞給更通用的HTML幫助器。我認爲這會工作,但後來我需要能夠告訴視圖應該使用哪個實現來繪製視圖,這看起來有問題,因爲它似乎模糊了視圖和控制器之間的界限。

看起來很明顯的一種不太吸引人的方法是從控制器傳遞一種管理標誌,該標誌將被泛型(在邏輯上不是類型泛型)工廠幫助程序中使用,並在其中構建邏輯以知道哪一系列使用方法。這樣可以保持模型和視圖不同,但感覺髒,因爲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提供的建議。它涉及創建一個新的模型來容納可能的控制屬性的超集,併爲每個不同的控制集(一個用於審計,一個用於審查)繪製新的視圖。它的問題是導致瀏覽API是醜陋:

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

每個控制器動作包含類似:

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); 

我無法弄清楚如何得到我的幫助通用在這方面的工作情況,此外,我想刪除減少明顯的代碼重複,所以這很快成爲:

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

@DrawControl("ID", ...) 

具有相同的控制器操作。這個問題(忽略View完全有功能)是因爲@functions塊必須包含在任何想要使用它們的視圖中(目前只有2個,但很快就會足夠擴展到5個以及誰知道我的前任將如何處理這件事)。我迅速再次修改了代碼,這一次帶回的助手(一般保持意見,模型和控制器的變化),最後結束了與此:

查看:

@(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她在那些被證明可以幫助情況的人之間進行迭代,而且他們沒有做到必要的程度。我相信還有待改進,但這是我迄今爲止所做的。

這樣做提供了一個非常簡單的API用於視圖使用,而無需知道或關心實現,它可以滿足我的預先存在的API的所有要求,只需稍作修改(最終在最小)。我不確定這是否是答案意圖的結果,但它是功能性的並提供了必要的簡單性。

希望我的頭痛會在未來幫助別人。