我是ASP的新手。净MVC。我在理解ViewModel的目的方面有一个问题。

什么是ViewModel,为什么我们需要一个ASP的ViewModel。NET MVC应用程序?

如果我能给出一个关于它的工作和解释的好例子,那就更好了。


当前回答

视图模型a是一个简单的类,它可以包含多个类属性。我们使用它来继承所有必需的属性,例如,我有两个类Student和Subject

Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}  
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}

现在我们想要在视图(MVC)中显示记录学生的名字和科目的名字,但不可能添加多个类,如:

 @model ProjectName.Model.Student  
 @model ProjectName.Model.Subject

上面的代码将抛出一个错误…

现在我们创建了一个类,可以给它起任何名字,但是这种格式“XyzViewModel”会让它更容易理解。这是继承的概念。 现在我们创建第三个类,名称如下:

public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}

现在我们在View中使用这个ViewModel

@ model ProjectName.Model.StudentViewModel

现在我们能够在View中访问StudentViewModel和继承类的所有属性。

其他回答

如果您有特定于视图的属性,并且与DB/Service/Data存储无关,那么使用ViewModels是一个很好的实践。比方说,您希望根据一个(或两个)DB字段选择一个复选框,但DB字段本身不是布尔值。虽然可以在模型本身中创建这些属性,并将其隐藏在数据绑定中,但您可能不希望根据此类字段和事务的数量使模型变得混乱。

如果特定于视图的数据和/或转换太少,您可以使用模型本身

编辑:我在我的博客上更新了这个答案:

http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development

我的回答有点长,但我认为将视图模型与其他类型的常用模型进行比较是很重要的,这样可以理解为什么它们不同,为什么它们是必要的。

总结一下,直接回答问题:

Generally speaking, a view model is an object that contains all the properties and methods necessary to render a view. View model properties are often related to data objects such as customers and orders and in addition, they also contain properties related to the page or application itself such as user name, application name, etc. View models provide a convenient object to pass to a rendering engine to create an HTML page. One of many reasons to use a view model is that view models provide a way to unit test certain presentation tasks such as handling user input, validating data, retrieving data for display, etc.

下面是实体模型的比较。dto方。模型)、表示模型和视图模型。

数据传输对象,又称“模型”

数据传输对象(DTO)是具有与数据库中的表模式匹配的属性的类。dto的命名源于它们在数据存储间来回传输数据的常用用法。 dto的特点:

业务对象-它们的定义依赖于应用程序数据。 通常只包含属性-没有代码。 主要用于向数据库传输数据和从数据库传输数据。 属性与数据存储中特定表上的字段完全匹配或紧密匹配。

数据库表通常是规范化的,因此dto通常也是规范化的。这使得它们在显示数据时用处有限。然而,对于某些简单的数据结构,它们通常表现得很好。

下面是dto的两个示例:

public class Customer
{
    public int ID { get; set; }
    public string CustomerName { get; set; }
}


public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public DateTime OrderDate { get; set; }
    public Decimal OrderAmount { get; set; }
}

演示模型

表示模型是用于在屏幕或报表上呈现数据的实用程序类。表示模型通常用于对由来自多个dto的数据组成的复杂数据结构进行建模。表示模型通常表示非规范化的数据视图。

表示模型的特点:

Are business objects – their definition is dependent on application data. Contain mostly properties. Code is typically limited to formatting data or converting it to or from a DTO. Presentation Models should not contain business logic. Often present a denormalized view of data. That is, they often combine properties from multiple DTOs. Often contain properties of a different base type than a DTO. For example, dollar amounts may be represented as strings so they can contain commas and a currency symbol. Often defined by how they are used as well as their object characteristics. In other words, a simple DTO that is used as the backing model for rendering a grid is in fact also a presentation model in the context of that grid.

表示模型是“根据需要”和“在需要的地方”使用的(而dto通常绑定到数据库模式)。表示模型可用于为整个页面、页面上的网格或页面上网格上的下拉列表建模。表示模型通常包含其他表示模型的属性。表示模型通常是为单一用途而构造的,例如在单个页面上呈现特定的网格。

一个演示模型示例:

public class PresentationOrder
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

视图模型

视图模型与表示模型相似,都是用于呈现视图的支持类。然而,它在构造方式上与表示模型或DTO有很大不同。视图模型通常包含与表示模型和dto相同的属性,因此,它们经常被混淆。

视图模型的特点:

Are the single source of data used to render a page or screen. Usually, this means that a view model will expose every property that any control on the page will need to render itself correctly. Making the view model the single source of data for the view greatly improves its capability and value for unit testing. Are composite objects that contain properties that consist of application data as well as properties that are used by application code. This characteristic is crucial when designing the view model for reusability and is discussed in the examples below. Contain application code. View Models usually contain methods that are called during rendering and when the user is interacting with the page. This code typically relates to event handling, animation, visibility of controls, styling, etc. Contain code that calls business services for the purpose of retrieving data or sending it to a database server. This code is often mistakenly placed in a controller. Calling business services from a controller usually limits the usefulness of the view model for unit testing. To be clear, view models themselves should not contain business logic but should make calls to services which do contain business logic. Often contain properties that are other view models for other pages or screens. Are written “per page” or “per screen”. A unique View Model is typically written for every page or screen in an application. Usually derive from a base class since most pages and screens share common properties.

视图模型组合

如前所述,视图模型是复合对象,因为它们组合了单个对象上的应用程序属性和业务数据属性。视图模型中常用的应用程序属性示例如下:

用于显示应用程序状态的属性,如错误消息、用户名、状态等。 用于设置控件的格式、显示、样式化或动画化的属性。 用于数据绑定的属性,如列表对象和保存用户输入的中间数据的属性。

下面的例子说明了为什么视图模型的复合性质是重要的,以及我们如何才能最好地构建一个高效且可重用的视图模型。

假设我们正在编写一个web应用程序。应用程序设计的要求之一是必须在每个页面上显示页面标题、用户名和应用程序名。如果我们想要创建一个页面来显示表示订单对象,我们可以修改表示模型如下所示:

public class PresentationOrder
{
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

这种设计可能可行,但如果我们想创建一个显示订单列表的页面呢?PageTitle、UserName和ApplicationName属性将会重复出现,并且变得难以处理。另外,如果我们想在类的构造函数中定义一些页级逻辑呢?如果我们为将要显示的每个订单创建一个实例,就不能再这样做了。

复合优于继承

下面是一种重构订单表示模型的方法,这样它就变成了一个真正的视图模型,对于显示单个PresentationOrder对象或PresentationOrder对象的集合非常有用:

public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public PresentationOrder Order { get; set; }
}


public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

查看上面的两个类,我们可以看到考虑视图模型的一种方式是,它是一个包含另一个表示模型作为属性的表示模型。顶层表示模型(即视图模型)包含与页面或应用程序相关的属性,而表示模型(属性)包含与应用程序数据相关的属性。

我们可以进一步设计并创建一个基视图模型类,它不仅可以用于PresentationOrders,还可以用于任何其他类:

public class BaseViewModel
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
}

现在我们可以像这样简化我们的PresentationOrderVM:

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public PresentationOrder Order { get; set; }
}

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

我们可以通过使BaseViewModel泛型来使它更具可重用性:

public class BaseViewModel<T>
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business property
    public T BusinessObject { get; set; }
}

现在我们的实现很轻松:

public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
    // done!
}

public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
    // done!
}

MVC没有视图模型:它有模型、视图和控制器。ViewModel是MVVM (Model-View-ViewModel)的一部分。MVVM派生自表示模型,在WPF中得到推广。在MVVM中也应该有一个模型,但是大多数人完全忽略了这个模式的要点,他们只有一个视图和一个视图模型。MVC中的模型与MVVM中的模型相似。

在MVC中,这个过程分为3个不同的职责:

视图负责将数据显示给用户 控制器负责页面流 模型负责业务逻辑

MVC不太适合web应用程序。它是Smalltalk为创建桌面应用程序引入的一种模式。web环境的行为完全不同。从桌面开发中复制一个40年前的概念并将其粘贴到web环境中并没有多大意义。然而,很多人认为这是可以的,因为他们的应用程序编译并返回正确的值。在我看来,这并不足以说明某种设计选择是可行的。

web应用程序中模型的一个例子可以是:

public class LoginModel
{
    private readonly AuthenticationService authentication;

    public LoginModel(AuthenticationService authentication)
    {
        this.authentication = authentication;
    }

    public bool Login()
    {
        return authentication.Login(Username, Password);
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

控制器可以这样使用它:

public class LoginController
{
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        bool success = model.Login();

        if (success)
        {
            return new RedirectResult("/dashboard");
        }
        else
        {
            TempData["message"] = "Invalid username and/or password";
            return new RedirectResult("/login");
        }
    }
}

你的控制器方法和模型将是小的,容易测试的,并且是切中要害的。

视图模型a是一个简单的类,它可以包含多个类属性。我们使用它来继承所有必需的属性,例如,我有两个类Student和Subject

Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}  
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}

现在我们想要在视图(MVC)中显示记录学生的名字和科目的名字,但不可能添加多个类,如:

 @model ProjectName.Model.Student  
 @model ProjectName.Model.Subject

上面的代码将抛出一个错误…

现在我们创建了一个类,可以给它起任何名字,但是这种格式“XyzViewModel”会让它更容易理解。这是继承的概念。 现在我们创建第三个类,名称如下:

public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}

现在我们在View中使用这个ViewModel

@ model ProjectName.Model.StudentViewModel

现在我们能够在View中访问StudentViewModel和继承类的所有属性。

视图模型是数据的概念模型。例如,它的用途是获取一个子集或组合来自不同表的数据。

您可能只需要特定的属性,因此这允许您只加载那些属性,而不添加不必要的属性。