每个页面的`ViewModel`(`Create.cshtml`和`Edit.cshtml`)?

时间:2011-11-01 19:18:53

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

问题

实际上有两个相关的问题:

  1. 我应该为每个页面创建一个ViewModel吗?
  2. 如果在为两个页面(Create.cshtmlEdit.cshtml)创建单个ViewModel类时没有问题,我如何以不同方式验证ViewModel(取决于正在使用的页面) )
  3. 来源

    视图模型

    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&gt;编辑方法

    [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

    谢谢大家的帮助!

4 个答案:

答案 0 :(得分:0)

我的理解是ViewModels和Views之间没有1:1的相关性。通常情况下,您将拥有一个View,它不需要ViewModel与它一起使用。

当且仅当您需要一个绝对平行且针对特定视图定制的模型时,您将需要创建一个ViewModel。在100%的情况下情况并非如此。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

就个人而言,我对2个视图模型没有问题,特别是如果(如Paul Tyng所建议的那样)你使用基类来编辑和创建场景时常用的字段。

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

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