C# 在MVC中跳过操作级别的模型验证
我有一个动作方法,它输出一个有多个子模型的模型。在其中一个子模型中,我有一些视图中不需要的附加属性 子模型-C# 在MVC中跳过操作级别的模型验证,c#,asp.net-mvc,C#,Asp.net Mvc,我有一个动作方法,它输出一个有多个子模型的模型。在其中一个子模型中,我有一些视图中不需要的附加属性 子模型-ProjectModel- [Required(ErrorMessage = "*")] public int Id { get; set; } [Required(ErrorMessage = "*")] public int SectorDivisionId { get; set; } [Required(ErrorMessage = "*")] [StringLength(250,
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()
- 创建新的视图模型
谢谢。干净的方法是针对不同的用例使用不同的视图模型 也就是说,您可以使用数据注释属性而不是使用数据注释属性来实现验证逻辑 在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 ...
}
}
公共类ProjectModel:IValidatableObject{
公共布尔IsEditUsecase{get;set;}
[必需(ErrorMessage=“*”)//每个用例都必需
公共int Id{get;set;}
//没有[Required]和[StringLength]属性
//因为只有在某些用例中才需要
公共字符串程序{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext){
//仅在编辑用例中发生的验证
如果(IsEditUsecase){
//验证“程序”属性
if(string.IsNullOrWhiteSpace(程序)){
返回新的ValidationResult(
“程序是必需的”,
新[]{“程序”}
);
}
否则如果(Program.Length>250){
返回新的ValidationResult(
“项目名称不应超过250个字符。”,
新[]{“程序”}
);
}
//验证编辑用例的其他属性。。。
}
//验证其他用例。。。
}
}
作为一个肮脏的黑客,我在我的razor页面中为所有导致ModelState验证错误的属性添加了隐藏字段。基本上,我为隐藏字段添加了一些默认值,现在效果很好。
虽然不推荐,但这是一个快速修复方法。您的编辑数据,因此一如既往,请使用视图模型(该视图模型将只包含您在视图中需要的属性)@StephenMuecke是的,但在这种情况下,我将不得不复制大量字段,这可能会导致我以后添加/删除的每个属性在将来重复。是否有其他解决方案?使用自定义ActionFilter,重写OnActionExecuting并调用modelState[“ProjectModel”]。Errors.Clear()@IvanZaruba我可以同时使用自定义筛选器和继承筛选器吗?或者它会冲突/覆盖-
modelState[“ProjectModel”]。Errors.Clear()代码>另一个想法-[Bind(Exclude=“ProjectModel”)]属性