在MVC中的动作级别跳过模型验证

时间:2018-01-29 11:19:54

标签: c# asp.net-mvc

我有一个动作方法,输出一个有多个子模型的模型。在其中一个子模型中,我有一些额外的属性,在我的视图中不需要。

子模型 - ProjectModel -

[Required(ErrorMessage = "*")]
public int Id { get; set; }
[Required(ErrorMessage = "*")]
public int SectorDivisionId { get; set; }
[Required(ErrorMessage = "*")]
[StringLength(250, ErrorMessage = "Project name should not be more than 250 characters.")]
public string Program { get; set; }

[Required(ErrorMessage = "*")]
[StringLength(25, ErrorMessage = "Project number should not be more than 25 characters.")]
public string ProjectNumber { get; set; }

public string WorkPackage { get; set; }

public string WorkPackageType { get; set; }

[Required(ErrorMessage = "*")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "*")]
public DateTime EndDate { get; set; }
public int ProjectDirectorId { get; set; }

因此,在将子模型初始化为我的主模型时,我只使用了我需要的那些属性,如下所示。

model.ProjectInfo = new ProjectModel()
{
    Id = projectId,
    ProjectNumber = prj.p.ProjectNumber,
    Director = prj.Director,
    Program = prj.p.Program,
    StartDate = prj.p.StartDate,
    EndDate = prj.p.EndDate,
    ProjectReviewPeriodList = projectReviewPeriodList.AsEnumerable().
                                Select(o => new ProjectReviewPeriodModel
                                {
                                    Id = o.Id,
                                    ProjectReviewTypeId = o.ProjectReviewTypeId,
                                    ProjectId = o.ProjectId,
                                    ReviewPeriod = o.ReviewPeriod,
                                    ReviewPeriodDate = o.ReviewPeriodDate                                                    
                                }).ToList()
};

现在,在发布表单时,我在全局级别有一个动作过滤器,用于验证模型。验证(ModelState.IsValid)对于我未根据需要初始化的子模型中的某些字段失败。

我想到了两个选择 -

  • 使用ModelState.Remove(<PropertyName>)跳过验证。这是不可能的,因为我正在使用全局级别操作过滤器。
  • 创建新视图模型

还有其他方法吗,最好是在动作方法级别?

如果有任何疑问,请告诉我,否则我可以更清楚地解释。

感谢。

2 个答案:

答案 0 :(得分:1)

干净的方法是将不同的ViewModel用于不同的用例。

话虽如此,您可以使用IValidatableObject实现验证逻辑,而不是使用Data Annotations属性。

在ViewModel中引入一个标志,用于指示用例,例如: IsEditUsecase。将此标志设置在您知道用例的位置,例如在控制器中。

然后只执行此用例所需的验证。

public class ProjectModel : IValidatableObject {

    public bool IsEditUsecase { get; set; }

    [Required(ErrorMessage = "*")] // required for every usecase
    public int Id { get; set; }

    // no [Required] and [StringLength] attributes 
    // because only required in some of the usecases
    public string Program { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
         // validation that occurs only in Edit usecase
         if (IsEditUsecase) {

             // Validate "Program" property
             if (string.IsNullOrWhiteSpace(Program)) {
                 yield return new ValidationResult(
                        "Program is required",
                        new[] { "Program" }
                 );
             } 
             else if (Program.Length > 250) {
                 yield return new ValidationResult(
                     "Project name should not be more than 250 characters.",
                     new[] { "Program" }
                 );
             }

             // validate other properties for Edit usecase ...
         }

         // validate other usecases ...
    }
}

答案 1 :(得分:0)

作为一个肮脏的黑客,我在剃刀页面中为所有导致ModelState验证错误的属性添加了隐藏字段。基本上我为隐藏字段添加了一些默认值,现在工作正常。 虽然不推荐,但它是一个快速修复。