【问题标题】:A `ViewModel` for each page (`Create.cshtml` and `Edit.cshtml`)?每个页面都有一个 `ViewModel`(`Create.cshtml` 和 `Edit.cshtml`)?
【发布时间】:2011-12-19 18:37:59
【问题描述】:

问题

其实有两个相关的问题:

  1. 我应该为每个页面创建一个 ViewModel 吗?
  2. 如果您在为两个页面(Create.cshtmlEdit.cshtml)创建单个 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()

创建.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

感谢大家的帮助!

【问题讨论】:

    标签: asp.net-mvc-3 viewmodel fluentvalidation


    【解决方案1】:

    我的理解是 ViewModel 和 View 之间没有 1:1 的相关性。通常,您将拥有一个不需要 ViewModel 与之配合的 View。

    当且仅当您需要一个完全平行且适合特定视图的模型时,您才需要创建一个视图模型。这不会是 100% 的情况。

    【讨论】:

    • 我完全同意!第二个问题呢?如果用户在我的ProjectValidator 类中编辑项目,如何忽略规则
    【解决方案2】:

    当页面之间的功能/用例/验证不同时,我使用不同的模型。如果除了存在 ID 或类似的东西之外它完全相同,我使用相同的模型,如果差异非常小,也可以使用相同的视图。

    由于您的验证不同,如果我这样做,我会创建两个不同的模型,以便我可以使用开箱即用的 DataAnnotations,尽管可能不需要验证。您还可以在编辑模型上为 name 设置只读属性,因为它不再可编辑。

    【讨论】:

    • 我不明白他的意思。我有一个 Edit.cshtmlCreate.cshtml 的 ViewModel 和一个用于验证此 ViewModel 的类。 我的问题是如果用户正在编辑项目,如何忽略规则。关于为每个页面创建一个 ViewModel,我觉得不舒服,会重复代码。
    • 如果代码在两个地方做同样的事情,它唯一的重复代码,它没有。您始终可以将基模型类用于共享功能。
    【解决方案3】:

    对我来说,同一个对象每次都必须有相同的验证,主要是为了确保对象的一致性,无论它是被创建还是编辑的。

    我认为您应该只创建一个验证,并编辑您的“存在”方法以验证它是新对象还是存储库中的当前对象。

    【讨论】:

    • Charles,验证是为了编辑和创建。使用职责分离的概念,我创建了一个负责验证 ViewModel 的类。问题是,如何使用相同的验证,但如果是新记录,则忽略某些规则。 (如上面的代码中所列)。
    【解决方案4】:

    就个人而言,我对 2 个视图模型没有任何问题,尤其是如果(如 Paul Tyng 建议的那样)您为编辑和创建场景常用的字段使用基类。

    但是,如果您真的只想要一个视图模型,那么您需要:

    • 向视图模型添加一个标志并在验证器中使用When() 方法。请注意,这不会生成适当的仅客户端验证
    • 定义第二个验证器并从控制器调用适当的验证器(即代替“自动”验证)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-24
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多