问题描述
我是 ASP.NET MVC 的新手.我在理解 ViewModel 的用途时遇到了问题.
I am new to ASP.NET MVC. I have a problem with understanding the purpose of a ViewModel.
什么是 ViewModel?为什么我们需要一个用于 ASP.NET MVC 应用程序的 ViewModel?
What is a ViewModel and why do we need a ViewModel for an ASP.NET MVC Application?
如果我能得到一个关于它的工作原理和解释的好例子就更好了.
If I get a good example about its working and explanation that would be better.
推荐答案
view model
表示您希望在视图/页面上显示的数据,无论是用于静态文本还是用于可以添加到数据库(或编辑)的输入值(如文本框和下拉列表).它与您的域模型
有所不同.它是视图的模型.
A view model
represents the data that you want to display on your view/page, whether it be used for static text or for input values (like textboxes and dropdown lists) that can be added to the database (or edited). It is something different than your domain model
. It is a model for the view.
假设您有一个 Employee
类代表您的员工域模型,它包含以下属性(唯一标识符、名字、姓氏和创建日期):
Let us say that you have an Employee
class that represents your employee domain model and it contains the following properties (unique identifier, first name, last name and date created):
public class Employee : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateCreated { get; set; }
}
视图模型与域模型的不同之处在于,视图模型仅包含您要在视图上使用的数据(由属性表示).例如,假设您要添加一条新员工记录,您的视图模型可能如下所示:
View models differ from domain models in that view models only contain the data (represented by properties) that you want to use on your view. For example, lets say that you want to add a new employee record, your view model might look like this:
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
如您所见,它仅包含两个属性.这两个属性也在员工域模型中.你可能会问这是为什么?Id
可能不是从视图中设置的,它可能是由 Employee 表自动生成的.并且 DateCreated
也可能在存储过程或应用程序的服务层中设置.所以 Id
和 DateCreated
在视图模型中是不需要的.当您以静态文本形式查看员工的详细信息(已被捕获的员工)时,您可能希望显示这两个属性.
As you can see it only contains two of the properties. These two properties are also in the employee domain model. Why is this you may ask? Id
might not be set from the view, it might be auto generated by the Employee table. And DateCreated
might also be set in the stored procedure or in the service layer of your application. So Id
and DateCreated
are not needed in the view model. You might want to display these two properties when you view an employee’s details (an employee that has already been captured) as static text.
加载视图/页面时,您的员工控制器中的 create action 方法将创建此视图模型的实例,如果需要填充任何字段,然后将此视图模型传递给视图/页面:
When loading the view/page, the create action method in your employee controller will create an instance of this view model, populate any fields if required, and then pass this view model to the view/page:
public class EmployeeController : Controller
{
private readonly IEmployeeService employeeService;
public EmployeeController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
public ActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
return View(model);
}
public ActionResult Create(CreateEmployeeViewModel model)
{
// Do what ever needs to be done before adding the employee to the database
}
}
您的视图/页面可能如下所示(假设您使用的是 ASP.NET MVC
和 Razor
视图引擎):
Your view/page might look like this (assuming you are using ASP.NET MVC
and the Razor
view engine):
@model MyProject.Web.ViewModels.CreateEmployeeViewModel
<table>
<tr>
<td><b>First Name:</b></td>
<td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
@Html.ValidationMessageFor(m => m.FirstName)
</td>
</tr>
<tr>
<td><b>Last Name:</b></td>
<td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
@Html.ValidationMessageFor(m => m.LastName)
</td>
</tr>
</table>
因此只对FirstName
和LastName
进行验证.使用 FluentValidation 你可能有这样的验证:
Validation would thus be done only on FirstName
and LastName
. Using FluentValidation you might have validation like this:
public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
public CreateEmployeeViewModelValidator()
{
RuleFor(m => m.FirstName)
.NotEmpty()
.WithMessage("First name required")
.Length(1, 50)
.WithMessage("First name must not be greater than 50 characters");
RuleFor(m => m.LastName)
.NotEmpty()
.WithMessage("Last name required")
.Length(1, 50)
.WithMessage("Last name must not be greater than 50 characters");
}
}
如果使用数据注释,它可能看起来像这样:
And with Data Annotations it might look this:
public class CreateEmployeeViewModel : ViewModelBase
{
[Display(Name = "First Name")]
[Required(ErrorMessage = "First name required")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Last name required")]
public string LastName { get; set; }
}
要记住的关键是视图模型只表示您想要使用的数据,没有别的.如果您有一个包含 30 个属性的域模型并且您只想更新一个值,您可以想象所有不必要的代码和验证.在这种情况下,您在视图模型中只会有这个值/属性,而不是域对象中的所有属性.
The key thing to remember is that the view model only represents the data that you want to use, nothing else. You can imagine all the unnecessary code and validation if you have a domain model with 30 properties and you only want to update a single value. Given this scenario you would only have this one value/property in the view model and not all the properties that are in the domain object.
一个视图模型可能不仅仅有来自一个数据库表的数据.它可以合并来自另一个表的数据.以我上面关于添加新员工记录的示例为例.除了只添加名字和姓氏之外,您可能还想添加员工所在的部门.此部门列表将来自您的 Departments
表.因此,现在您在一个视图模型中拥有来自 Employees
和 Departments
表的数据.然后您需要将以下两个属性添加到您的视图模型并用数据填充它:
A view model might not only have data from one database table. It can combine data from another table. Take my example above about adding a new employee record. Besides adding just the first and last names you might also want to add the department of the employee. This list of departments will come from your Departments
table. So now you have data from the Employees
and Departments
tables in one view model. You will just then need to add the following two properties to your view model and populate it with data:
public int DepartmentId { get; set; }
public IEnumerable<Department> Departments { get; set; }
编辑员工数据(已添加到数据库的员工)时,它与我上面的示例没有太大区别.创建一个视图模型,例如将其命名为 EditEmployeeViewModel
.在这个视图模型中只有你想要编辑的数据,比如名字和姓氏.编辑数据并单击提交按钮.我不会太担心 Id
字段,因为 Id
值可能会在 URL 中,例如:
When editing employee data (an employee that has already been added to the database) it wouldn’t differ much from my example above. Create a view model, call it for example EditEmployeeViewModel
. Only have the data that you want to edit in this view model, like first name and last name. Edit the data and click the submit button. I wouldn’t worry too much about the Id
field because the Id
value will probably been in the URL, for example:
http://www.yourwebsite.com/Employee/Edit/3
获取此 Id
并将其与您的名字和姓氏值一起传递到您的存储库层.
Take this Id
and pass it through to your repository layer, together with your first name and last name values.
删除记录时,我通常遵循与编辑视图模型相同的路径.我也会有一个 URL,例如:
When deleting a record, I normally follow the same path as with the edit view model. I would also have a URL, for example:
http://www.yourwebsite.com/Employee/Delete/3
当视图第一次加载时,我会使用 Id
为 3 从数据库中获取员工的数据.然后我只会在我的视图/页面上显示静态文本,以便用户可以看到正在删除的员工.当用户单击删除"按钮时,我将只使用 Id
值 3 并将其传递给我的存储库层.您只需要 Id
即可从表中删除记录.
When the view loads up for the first time I would get the employee’s data from the database using the Id
of 3. I would then just display static text on my view/page so that the user can see what employee is being deleted. When the user clicks the Delete button, I would just use the Id
value of 3 and pass it to my repository layer. You only need the Id
to delete a record from the table.
还有一点,你真的不需要每个动作的视图模型.如果它是简单的数据,那么只使用 EmployeeViewModel
就可以了.如果是复杂的视图/页面并且它们彼此不同,那么我建议您为每个视图使用单独的视图模型.
Another point, you don’t really need a view model for every action. If it is simple data then it would be fine to only use EmployeeViewModel
. If it is complex views/pages and they differ from each other then I would suggest you use separate view models for each.
我希望这能消除您对视图模型和域模型的任何混淆.
I hope this clears up any confusion that you had about view models and domain models.
这篇关于MVC中的ViewModel是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!