每个页面都有一个“ViewModel”(“Create.cshtml”和“Edit.cshtml”)?
问题
实际上有两个相关的问题:
- 我应该为每个页面创建一个ViewModel吗?
- 如果您在为两个页面(
Create.cshtml
和Edit.cshtml
)创建单个 ViewModel 类时没有问题,我如何以不同的方式验证 ViewModel(取决于在正在使用的页面上)
源
ViewModel
public class ProjectViewModel
{
public string Name { get; set; }
public string Url { get; set; }
public string Description { get; set; }
}
Edit.cshtml
@using BindSolution.ViewModel.Project
@model ProjectViewModel
@{
ViewBag.Title = Model.Name;
}
@Html.EditorForModel()
Create.cshtml
@using BindSolution.ViewModel.Project
@model ProjectViewModel
@{
ViewBag.Title = "New Project";
}
@Html.EditorForModel()
ProjectValidator.cs
public class ProjectValidator : AbstractValidator<ProjectViewModel>
{
private readonly IProjectService _projectService;
public ProjectValidator(IProjectService projectService)
{
_projectService = projectService;
RuleFor(p => p.Name)
.NotEmpty().WithMessage("required field")
/*The validation should be made only if the page is Create.cshtml. That is, if you are creating a new project.*/
.When(p => p.??) //Problem Here!!
.Must(n => !_projectService.Exist(n)).WithMessage("name already exists");
RuleFor(p => p.Url)
.NotEmpty().WithMessage("required field");
}
}
请注意,如果用户正在编辑现有的项目中,不应再次验证属性 name
。
ProjectController.cs >编辑方法
[HttpPost]
public ActionResult Edit(Guid projectID, ProjectViewModel model)
{
var project = _projectService.Repository.Get(projectID);
if (ModelState.IsValid && TryUpdateModel(project))
{
_projectService.Repository.Attach(project);
if (_projectImageWrap.Create(project) && _projectService.Repository.Save() > 0)
return AjaxRedirect("Index");
}
return View(model);
}
注意
如果我为每个页面创建一个 ViewModel,则会出现代码重复,因为页面具有相同的属性。
在 ViewModel 上添加一个属性来指示正在显示的页面并不能解决我的问题,即实例化 ViewModel,我使用 AutoMapper。
为了验证数据,我使用 FluentValidator。
感谢大家的帮助!
Questions
There are actually two related questions:
- Should I create a ViewModel for each page?
- If you do not have problems in creating a single ViewModel class for the two pages (
Create.cshtml
andEdit.cshtml
) how can I validate the ViewModel in different ways (depending on the page that is being used)
Source
ViewModel
public class ProjectViewModel
{
public string Name { get; set; }
public string Url { get; set; }
public string Description { get; set; }
}
Edit.cshtml
@using BindSolution.ViewModel.Project
@model ProjectViewModel
@{
ViewBag.Title = Model.Name;
}
@Html.EditorForModel()
Create.cshtml
@using BindSolution.ViewModel.Project
@model ProjectViewModel
@{
ViewBag.Title = "New Project";
}
@Html.EditorForModel()
ProjectValidator.cs
public class ProjectValidator : AbstractValidator<ProjectViewModel>
{
private readonly IProjectService _projectService;
public ProjectValidator(IProjectService projectService)
{
_projectService = projectService;
RuleFor(p => p.Name)
.NotEmpty().WithMessage("required field")
/*The validation should be made only if the page is Create.cshtml. That is, if you are creating a new project.*/
.When(p => p.??) //Problem Here!!
.Must(n => !_projectService.Exist(n)).WithMessage("name already exists");
RuleFor(p => p.Url)
.NotEmpty().WithMessage("required field");
}
}
Note that if the user is editing an existing project, validation of the property name
should not be done again.
ProjectController.cs > Edit method
[HttpPost]
public ActionResult Edit(Guid projectID, ProjectViewModel model)
{
var project = _projectService.Repository.Get(projectID);
if (ModelState.IsValid && TryUpdateModel(project))
{
_projectService.Repository.Attach(project);
if (_projectImageWrap.Create(project) && _projectService.Repository.Save() > 0)
return AjaxRedirect("Index");
}
return View(model);
}
Notes
If I create a ViewModel for each page, there is a duplication of code since pages have the same properties.
Add a property on the ViewModel indicating what page it is being displayed does not solve my problem as to instantiate the ViewModel, I use AutoMapper.
To validate the data, I use FluentValidator.
Thank you all for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我的理解是 ViewModel 和 View 之间不存在 1:1 的相关性。通常,您会拥有一个不需要 ViewModel 与之配合的视图。
当且仅当您需要绝对并行并针对特定视图定制的模型时,您才需要创建 ViewModel。情况并非 100% 都是如此。
My understanding is that there isn't a 1:1 correlation between ViewModels and Views. Oftentimes you will have a View that will not require a ViewModel to go alongside with it.
You will want to create a ViewModel if and only if you need a Model absolutely paralleled and tailored to a specific View. This will not be the case 100% of the time.
当页面之间的功能/用例/验证不同时,我使用不同的模型。如果除了 ID 或类似内容之外完全相同,我会使用相同的模型,如果差异很小,也可以仅使用相同的视图。
由于您的验证不同,如果我这样做,我将创建两个不同的模型,以便我可以使用开箱即用的 DataAnnotations,并进行您的验证,尽管可能不需要。您还可以在编辑模型上具有名称的只读属性,因为它不再可编辑。
When the functionality / use case /validation is different between the pages I use different models. If its the exact same besides the presence of an ID or something similar I use the same model, and its also possible to just use the same view if the differences are pretty minor.
Since your validation is different, if I were doing it I would create two different models so that I could use the out of the box DataAnnotations, with your validation though it may not be required. You could also on the edit model have a readonly property for name since its not editable any longer.
对我来说,同一个对象每次都必须具有相同的验证,主要是为了确保对象的一致性,无论它是创建还是编辑的。
我认为您应该只创建一个验证,并编辑您的“存在”方法以验证它是新对象还是存储库中的当前对象。
For me the same object must have the same validation on every time, in main to ensure the consistence of the object, independently if it was created or edited.
i think that you should create only one validation, and edit your "exists" method to pass to verify if it is a new object or the current object in repository.
就我个人而言,我对 2 个视图模型没有问题,特别是如果(正如 Paul Tyng 建议的那样)您对编辑和创建场景常用的字段使用基类。
但是,如果您确实只想要一个视图模型,那么您需要:
Personally, I don't have a problem with 2 view models, especially if (as Paul Tyng suggested) you use a base class for the fields that are common to edit and create scenarios.
However, if you really only want a single view model then you would either need to:
提供另一个视图 Edit.cshtml,它将允许用户编辑所选项目的数据。
创建另一个基于 ItemName 的视图 Query.cshtml 将允许用户查询 Inventory 表。
计算总利润(销售数量乘以(销售价格-购买成本)。显示总利润。
(奖励)创建另一个视图 Sell.cshtml,该视图将指示商品的销售情况。向 NumberSold 添加 1,并从 NumberInventory 中减去 1,以获得选定的记录。
Provide another view Edit.cshtml which will allow the user to edit the data for a selected item.
Create another view Query.cshtml which based on the ItemName will allow the users to query the Inventory table.
Perform the calculation for the total profit (numbersold times (saleprice-purchasecost). Display the total profit.
(BONUS) Create another view Sell.cshtml that will indicate the sale of an item. Adding one to NumberSold and subtract one from NumberInventory for the selected record.