2012-01-24 36 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的所有要求,只需稍作修改(最终在最小)。我不确定这是否是答案意图的结果,但它是功能性的并提供了必要的简单性。

希望我的头痛会在未来帮助别人。