MVC减少重复代码

时间:2012-05-22 15:13:28

标签: c# asp.net-mvc asp.net-mvc-3 reflection razor

我刚刚开始使用并且爱上了MVC设计模式。

我唯一的宠儿就是它似乎产生了很多重复的代码。例如。

我有一个标准的MVC应用程序,我的数据库(模型)在一个项目中,与另一个项目中的控制器/视图/视图模型分开,再次与我在另一个项目中的测试方法分开。一切都很好。

型号: 现在,我在我的数据库项目中有一堆很好的EF4类,我必须在我的真实项目中使用ViewModel来访问我的数据。这里没问题。

控制器: 但是,我拥有的每个控制器,基本上都是一样的。它从ViewModel获取并设置数据,因此每个控制器的不同之处在于它只获得不同的数据,它们基本上都以相同的方式完成相同的工作。 (我目前有9个,但这很容易爆炸到50岁以上)。

例如:

public class Dummy1Controller : Controller
{
    private MyProj.Data.Entities _entities = new Data.Entities();
    private MyProj.Data.Entities2 _coreEntities = new Data.Entities2();

    //GET: /Customers/
    public ActionResult Index()
    {
        if (_entities.table1.Count() == 0) return View();

        var pastObj = _entities.table1.First();
        return View(new Table1ViewModel()
        {
            Id = pastObj.Id,
            FirstName = pastObj.FirstName,
            LastName = pastObj.LastName,
            .
            .
            .
            .
        });
    }
}

public class Dummy2Controller : Controller
{
    private MyProj.Data.Entities _entities = new Data.Entities();
    private MyProj.Data.Entities2 _coreEntities = new Data.Entities2();

    //GET: /Vehicles/
    public ActionResult Index()
    {
        if (_entities.table2.Count() == 0) return View();

        var pastObj = _entities.table2.First();
        return View(new Table1ViewModel()
        {
            RegNo = pastObj.RegNo,
            Make = pastObj.Make,
            Model = pastObj.Model,
            .
            .
            .
            .
        });
    }
}

public class Dummy3Controller : Controller
{
    private MyProj.Data.Entities _entities = new Data.Entities();
    private MyProj.Data.Entities2 _coreEntities = new Data.Entities2();

    //GET: /Invoices/
    public ActionResult Index()
    {
        if (_entities.table3.Count() == 0) return View();

        var pastObj = _entities.table3.First();
        return View(new Table1ViewModel()
        {
            InvNo = pastObj.InvNo,
            Amount = pastObj.Amount,
            Tax = pastObj.Tax,
            .
            .
            .
            .
        });
    }
}

查看: 从控制器生成的每个视图都很有效。 Execpt,唯一改变的是数据(带有标签和文本框的字段)。再一次,他们都做同样的工作(但使用不同的数据集)。

@model MyProject.Web.ViewModels.Table1ViewModel

@{
    ViewBag.Title = "Index";
}

<link href="@Url.Content("~/Content/CSS/GenericDetailStyles.css")" rel="stylesheet" type="text/css" />

<section id="content">
    <div id="table">
        <div>
            <h2>Customer</h2>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.Id)</div>
            <div class="right">@Html.TextBoxFor(model => model.Id)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.FirstName)</div>
            <div class="right">@Html.TextBoxFor(model => model.FirstName)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.LastName)</div>
            <div class="right">@Html.TextBoxFor(model => model.LastName)</div>
        </div>
        .
        .
        .
        .
    </div>
</section>

@{Html.RenderAction("Index", "FooterPartial");}


--------------------------------------------------------------------------------------


@model MyProject.Web.ViewModels.Table2ViewModel

@{
    ViewBag.Title = "Index";
}

<link href="@Url.Content("~/Content/CSS/GenericDetailStyles.css")" rel="stylesheet" type="text/css" />

<section id="content">
    <div id="table">
        <div>
            <h2>Vehicle</h2>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.RegNo)</div>
            <div class="right">@Html.TextBoxFor(model => model.RegNo)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.Make)</div>
            <div class="right">@Html.TextBoxFor(model => model.Make)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.PatientID)</div>
            <div class="right">@Html.TextBoxFor(model => model.Model)</div>
        </div>
        .
        .
        .
        .
    </div>
</section>

@{Html.RenderAction("Index", "FooterPartial");}


--------------------------------------------------------------------------------------


@model MyProject.Web.ViewModels.Table3ViewModel

@{
    ViewBag.Title = "Index";
}

<link href="@Url.Content("~/Content/CSS/GenericDetailStyles.css")" rel="stylesheet" type="text/css" />

<section id="content">
    <div id="table">
        <div>
            <h2>Invoice</h2>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.InvNo)</div>
            <div class="right">@Html.TextBoxFor(model => model.InvNo)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.Amount)</div>
            <div class="right">@Html.TextBoxFor(model => model.Amount)</div>
        </div>
        <div class="row">
            <div class="left">@Html.LabelFor(x=>x.Tax)</div>
            <div class="right">@Html.TextBoxFor(model => model.Tax)</div>
        </div>
        .
        .
        .
        .
    </div>
</section>

@{Html.RenderAction("Index", "FooterPartial");}

问题: 我想制作一个单独的控制器,并使其动态化。这样它就可以从不同的视图模型中读取数据。 (为什么9或50个控制器基本上做同样的工作)

然后我想对这些观点做同样的事情。这样就可以动态生成不同的字段。 (为什么有9或50个视图都在做同样的工作)。如果视图基于控制器,则视图应该能够根据其属性进行更改。

基本上我想要的是找到一种方法来告诉控制器从viewmodel X或VM -Y或VM-Z ect读取它应该能够生成属性,检索相关数据,并将其传递给视图在接收时将生成带有标签和文本框的字段。

我想我想知道是否有任何方法可以使用反射来做到这一点。由于视图模型是具有简单属性的基本类。有人可能会创建一个基本控制器类,它具有读取指定viewmodel对象的方法,获取其属性,同时读入关联表,并将该表中的字段与类中的属性进行匹配。最后,可以从表中传入记录进行显示。然后可以使用某种剃刀,c#或javascript自动生成视图。

如果可能的话,任何女儿都会受到欢迎。

4 个答案:

答案 0 :(得分:10)

您可以使用 AutoMapper 删除模型/实体之间复制值的所有代码。

另外,请考虑使用布局,数据注释属性和模板(使用Html.DisplayFor和Html.EditorFor)缩小视图。

http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

您可以研究创建通用基本控制器类的可能性,它将采用模型和实体的类型,并将包含CRUD操作的通用逻辑,但它可能是一个太过分的步骤,并在以后阻碍您的开发。 / p>

答案 1 :(得分:5)

我认为一个动态控制器可能是一个太过分的步骤 - 当你使一切通用,然后你的一个视图需要比数据库的简单映射更复杂的东西时会发生什么 - 你扩展你的'通用视图控制器'处理这个?可能会结束here.

您应该查看Automapper,以消除处理视图模型的一些重复性。

http://automapper.codeplex.com/

答案 2 :(得分:0)

您可以为对象或者基类生成EditFor / Model模板,无论它是什么,然后只创建一个视图,它将接受您的模型,其元数据(在mvc metadataproviders的帮助下),并构建动态地根据。
this post涵盖了它可以在mvc2中完成,但你也可以很容易地将这种技术应用到mvc 3中。
我在一个项目mi中使用这样的模板,我有几十个不同的实体,都拥有相同的外观和感觉。借助我自己的Metadataprovider的帮助,这也帮助我获得字段的顺序,并且在每个视图中它们应该是可见的,我构建了一个视图,以显示我的所有实体

答案 3 :(得分:0)

我同意其他人的观点,即在您的应用程序中使用一个动态控制器来处理所有模型和视图太过分了。还有其他方法可以减少控制器中的代码量。这里的其他答案都提到了AutoMapper,这是一个很棒的工具。 AutoMapper的发明者Jimmy Bogard也有一个great video here,其中包括你可以做的其他事情来减少控制器中的代码量。

就视图而言,您已经拥有一个使用EditorTemplates处理所有控制器的视图。您可以创建一个自定义的EditorTemplate,它将使用反射来检查模型并相应地渲染输入字段。这全都使用“模型元数据”,并且有a good post on that by Brad Wilson here