8

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

我对它唯一的不满是它似乎产生了很多重复的代码。例如。

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

模型:现在,我的数据库项目中有一堆不错的 EF4 类,我必须在我的实际项目中使用 ViewModels 来访问我的数据。这里没问题。

控制器:但是,我拥有的每个控制器基本上都在做同样的事情。它从 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,
            .
            .
            .
            .
        });
    }
}

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

@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 个视图都在做同样的工作)。如果视图基于控制器,则视图应该能够根据其属性进行更改。

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

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

任何关于这是否可能的教导都将受到欢迎。

4

4 回答 4

10

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

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

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

您可以研究创建通用基础控制器类的可能性,该类将采用模型和实体的类型,并将包含用于 CRUD 操作的通用逻辑,但这可能是一个过分的步骤,并且会阻碍您以后的开发。

于 2012-05-22T15:14:48.480 回答
5

我认为一个动态控制器可能会走得太远——当你把所有东西都变成通用的,然后你的一个视图需要比简单的数据库映射更复杂的东西时会发生什么——你扩展你的“通用视图控制器”来处理有了这个?可能会在这里结束。

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

http://automapper.codeplex.com/

于 2012-05-22T15:17:22.327 回答
0

您可以为对象或您的基类生成一个 EditFor/Model 模板,无论它是什么,然后只制作一个视图,该视图将接受您的模型、它的元数据(在 mvc metadataproviders 的帮助下),并根据动态构建字段.
这篇文章涵盖了它可以在 mvc2 中完成的方法,但你也可以轻松地将这种技术应用于 mvc 3。
我在我正在处理的项目中使用这样的模板,我有几十个不同的实体,都共享相同的外观和感觉。在我自己的 Metadataprovider 的帮助下,这也有助于我获取字段的顺序以及它们是否应该在每个视图中可见,我构建了一个视图来准确显示我的所有实体

于 2012-05-22T15:18:14.890 回答
0

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

就视图而言,您已经可以使用 EditorTemplates 拥有一个处理所有控制器的视图。您可以创建一个自定义的 EditorTemplate,它将使用反射来检查模型并相应地呈现输入字段。这一切都使用“模型元数据”,Brad Wilson 在这里有一篇很好的文章

于 2012-05-22T21:40:38.757 回答