【MVC】ASP.NET MVC ViewModel

使用ViewModels在ASP.NET MVC应用程序中管理数据和组织代码

ViewModel的概念不仅适用于ASP.NET MVC,因为您将在整篇网页中看到有关MVC,MVP和MVVM模式的文章和博客文章中对ViewModels的引用。这些帖子和文章可以围绕任何数量的技术,如ASP.NET,Silverlight,WPF或MVC ...本文将调查ViewModels适用于ASP.NET MVC的世界。

什么是ASP.NET MVC ViewModel?

在ASP.NET MVC中,ViewModels允许您将来自一个或多个数据模型或源的多个实体变形为单个对象,并针对视图的消耗和渲染进行优化。下图展示了ViewModel的概念:

ViewModel的目的是让视图具有单个对象进行渲染,从而减少视图中对UI逻辑代码的需求,否则这些代码是必需的。这意味着该视图唯一责任或关注点是呈现该单个ViewModel对象,帮助更清晰地分离关注点(SoC)。关注点是具有特定目的(即关注点)的应用程序的不同方面,并且保持这些方面不同意味着您的应用程序更加有组织,代码更专注。将数据操作代码放在远离视图和控制器的位置,强制执行SoC。

在MVC中使用ViewModels可实现更精细的粒度和更好的SoC,从而提供更易于维护和可测试的代码。请记住,单元测试是关于测试小单元的

随着更好的编码实践,有很多商业原因说明为什么你可能会考虑使用ViewModels:

  • 将查询数据的下拉列表合并到相关实体中
  • 主细节记录视图
  • 分页:结合实际数据和分页信息
  • 像购物车或用户配置文件小部件这样的组件
  • 仪表板,具有多个不同数据源
  • 报告,通常包含汇总数据

上述场景对于各种应用程序都很常见,并且处理比基本的CRUD格式的数据页面更复杂的数据(例如,简单的1:1映射到数据库表)。例如,提供状态列表,并确保与当前客户状态相匹配的状态,意味着您需要提供两组数据一组客户/状态数据,如下图所示。

某些场景(如代表美国状态的查找表)可以轻松地与ViewModels或ViewBag / ViewData对象一起使用,因此有时可能会有一些重叠。由应用程序架构师和开发人员决定什么对他们的确切用例最有效。

创建一个ViewModel

尽管一个ViewModel由多个实体组成,但ViewModel的核心仍然只是一个类 - 并且它甚至不会像许多MVC类那样继承任何特殊的东西。

从物理上看,ViewModels可以存在于不同的位置,如下所示:

  • 在名为ViewModels的文件夹中,该文件夹驻留在项目的根目录中。(小应用程序)
  • 作为从MVC项目引用的.dll(任何大小的应用程序)
  • 在作为服务层的单独项目中,用于生成视图/内容特定数据的大型应用程序。(企业应用程序)

由于ViewModel只是一个类,因此开始使用ViewModel的最简单方法是创建一个名为ViewModels的新文件夹并为其添加一个新的代码文件。

要创建CustomerViewModel ViewModel,请将Customer和StatesDictionary类型添加为属性以形成一个CustomerViewModel类。在下面的示例中,CustomerViewModel类包含新定义的属性。

公共  CustomerViewModel

{

    公共客户{get; 组; }

    public StatesDictionary States {get; 组; }

    公共 CustomerViewModel(客户客户)

    {

        客户=客户;

        States = new StatesDictionary();

    }

}

通常,ViewModels包含单词“ViewModel”作为其名称的一部分; 然而,在这里工作的约定是为了保持代码可读性的一致性,因为MVC中的其他类也在其名称中声明了它们的意图(例如,控制器的名称,操作方法等...在名称中使用约定)。

StatesDictionary类是一个简单的Dictionary对象,它包含两个字符串类型的参数。该类还包含词典中所有成员的定义(即状态数据)。StatesDictionary类中唯一的属性是StateSelectList,它是Html Helpers用来呈现显示状态列表的HTML <select>元素的对象。StateSelectList属性中的类型Dictionary <string,string>分别映射到状态缩写和状态名称。

公共  StatesDictionary

{

    公共 静态 SelectList StateSelectList

    {

        get { return  new SelectList(StateDictionary,“Value”“Key”); }

    } 

    public  static  readonly IDictionary < stringstring >

        StateDictionary = new Dictionary < stringstring > {

      { “选择...”“” }

    ,{ “Alabama”“AL” }

    ,{ “阿拉斯加”“AK” }

    ,{ “Arizona”“AZ” }

    ,{ “阿肯色州”“AR” }

    ,{ “California”“CA” }

    //代码继续添加状态...

    }; 

}

存在于所有类型的应用程序中的数据位于小列表中,并且不常发生变化,如StatesDictionary类。在现实世界的应用程序中,您会发现处理查找数据的各种方法,例如状态列表(通常是XML文件和SQL表)。您可以将StateDictionary方法中的代码替换为使用Entity Framework中的实体,从文件中读取数据或您需要的任何数据访问代码。

创建ViewModel后,接下来的步骤是在控制器中实例化它并将其返回到视图。

获取ViewModel的视图

从控制器开始...

将ViewModel发送到视图进行渲染将与处理模型时的工作方式相同。由于它只是一个类,视图不知道模型或ViewModel来自哪里,并且不关心。您可以在控制器中创建ViewModel类的实例,或者在使用IoC容器时解析它。请记住,就像您使用视图一样,您应该让控制器清理不必要的代码,这意味着只有取得模型或ViewModel的代码才属于此处,并且只有更多。

public ActionResult Edit(int id)

{

    Customer customer = context.Customers.Single(x => x.Id == id);

    var customerViewModel = new CustomerViewModel(customer);

    返回 View(customerViewModel);

}

然后该视图呈现ViewModel ...

为了使视图知道要使用哪个对象,请将@model关键字设置为指向ViewModel,就像您对常规模型已经使用的那样。

@model FourthCoffee.Web.ViewModels.CustomerViewModel

由于Customer对象是ViewModel的属性,因此您将看到model.Class.Property语法来访问ViewModel数据,与以下代码行类似。

< div  class =“editor-label” >

    @ Html.LabelFor(model = > model.Customer.FirstName)

</ div >

< div  class =“editor-field” >

    @ Html.EditorFor(model = > model.Customer.FirstName)

    @ Html.ValidationMessageFor(model = > model.Customer.FirstName)

</ div >

@ * ...查看代码继续渲染属性... * @

此外,您可以编辑编辑/创建视图,以便包含状态列表的DropDownList将显示,并显示与客户相匹配的正确状态。

< div  class =“editor-field” >    

    @ Html.DropDownList(“状态”,新的SelectList(StatesDictionary.StateSelectList, 

                       “Value”,“Text”,Model.Customer == null?“”:Model.Customer.State))

    @ Html.ValidationMessageFor(model = > model.Customer.State)

</ div >

正如您可能已经注意到的那样,使用ViewModel就像使用ViewBag或ViewData对象一样简单。但是,ViewModels提供了更易于测试和优化的额外优势。

检查结果

在用户导航到浏览器中的/ Customers / Edit / 1 URL后,Razor视图引擎将呈现CustomerViewModel,类似于以下屏幕快照。

按照预期,状态DropDownList显示该客户的状态和当前状态。

深入研究ViewModels

由于ViewModel渲染的模型类和数据库表之间不再具有这些1:1映射的预处理数据,因此您需要自己创建映射。您可以手动映射小型ViewModels,但在映射较大的类时,特别是在处理父子孙,多级或复杂数据时,这会很快变得繁重。这就是AutoMapper等工具发挥作用的地方。通过AutoMapper,您可以更轻松地手动设置ViewModel和模型之间的映射,或者编写您自己的映射器

以下是使用ViewModels的一些技巧:

  • 仅放入将在ViewModel中呈现的数据。
  • 该视图应该指导ViewModel的属性,这样它就更适合渲染和维护。
  • 当ViewModel变得复杂时使用映射器。

一些可以帮助您为模型和ViewModel生成POCO(Plain Old CLR对象)的工具是:

POCO发生器

EF POCO模板

除了这些工具,您还可以使用MvcScaffolding根据ViewModel创建操作和视图。MvcScaffolding,ASP.NET团队成员Steve Sanderson的发明,可以让您更轻松快捷地创建CRUD,存储库,单元测试和其他模板。点击此处查看Steve的MvcScaffolding多部分系列MvcScaffolding与ViewModels以及模型一起使用。

您应该始终更喜欢使用ViewModel,而不是实例化多个模型并将该操纵代码放入控制器中。

概要

当您需要处理比其他对象允许的更复杂的数据时,ViewModels可帮助您组织和管理MVC应用程序中的数据。使用ViewModels可以让您灵活地使用您认为合适的数据。ViewModels区域通常比模型+ ViewBag / ViewData对象更灵活地访问多个数据源。

猜你喜欢

转载自blog.csdn.net/mr_xuzhe/article/details/79493375