Asp.net mvc 如何在DB实体的子模型上使用自定义验证属性?
摘要:Asp.net mvc 如何在DB实体的子模型上使用自定义验证属性?,asp.net-mvc,data-annotations,dbcontext,Asp.net Mvc,Data Annotations,Dbcontext,摘要: 我希望数据注释验证程序引用同一类中的另一个属性(TitleAuthorAndPublishingConfiguration) 但是,不会直接对此类调用DB.SaveChanges()。而是在这个类的父类(WebsiteConfiguration)上调用它 因此,validationContext.ObjectType正在返回WebsiteConfiguration,我无法在数据批注验证器中引用标题作者和发布配置的属性 WebsiteConfiguration.cs public cla
我希望数据注释验证程序引用同一类中的另一个属性(
TitleAuthorAndPublishingConfiguration
)
但是,不会直接对此类调用DB.SaveChanges()。而是在这个类的父类(WebsiteConfiguration
)上调用它
因此,validationContext.ObjectType
正在返回WebsiteConfiguration
,我无法在数据批注验证器中引用标题作者和发布配置的属性
WebsiteConfiguration.cs
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
ApplicationDbContext.cs
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
验证程序代码
public void SeedWebsiteConfiguration()
{
var titleAuthorAndPublishingConfiguration = new TitleAuthorAndPublishingConfiguration()
{
// seed values
};
var bookChaptersAndSectionsConfiguration = new BookChaptersAndSectionsConfiguration()
{
// seed values
};
var socialMediaLoginConfiguration = new SocialMediaLoginsConfiguration()
{
// seed values
};
var tagGroupsConfiguration = new TagGroupsConfiguration()
{
// seed values
};
var websiteConfiguration = new WebsiteConfiguration()
{
TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration,
BookChaptersAndSections = bookChaptersAndSectionsConfiguration,
SocialMediaLogins = socialMediaLoginConfiguration,
TagGroups = tagGroupsConfiguration
};
DB.WebsiteConfiguration.Add(websiteConfiguration);
DB.SaveChanges();
}
public class RequiredIfOtherFieldIsEnabledAttribute : ValidationAttribute
{
private string _ifWhatIsEnabled { get; set; }
public RequiredIfOtherFieldIsEnabledAttribute(string IfWhatIsEnabled)
{
_ifWhatIsEnabled = IfWhatIsEnabled;
}
protected override ValidationResult IsValid(object currentPropertyValue, ValidationContext validationContext)
{
var isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled);
if (isEnabledProperty == null)
{
return new ValidationResult(
string.Format("Unknown property: {0}", _ifWhatIsEnabled)
);
}
var isEnabledPropertyValue = (bool)isEnabledProperty.GetValue(validationContext.ObjectInstance, null);
if (isEnabledPropertyValue == true)
{
if (String.IsNullOrEmpty(currentPropertyValue.ToString()))
{
return new ValidationResult(String.Format("This field is required if {0} is enabled", isEnabledProperty));
}
}
return ValidationResult.Success;
}
}
问题
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
我是否可以通过validationContext
访问子模型属性
我的方法是否被误导了?是否有更好的方法将多个模型作为较大模型的一部分存储在单个DB表中
我不希望有多个配置表和对数据库的调用。(本例中有4个子模型,但在下一个应用中可能有10多个子模型。)
上面的设置在很多方面满足了我的需要。但我不想放弃子模型上的DataAnnotation功能
奖金问题
我遇到过一些类似这样的帖子:
但这已经是4年前的事了,我想知道从那以后是否有什么变化
我是否在尝试做一些基本上不可能(或至少非常困难)的事情
我是否在尝试做一些基本上不可能的事情(或者至少是不可能的)
很难吗
不,有一个非常简单的解决方案,它与使用DataAnnotation的框架和技术完美集成
您可以创建由EF Validation调用的自定义ValidationAttribute
,并在内部调用Validator.TryValidateObject
。这样,当EF调用CustomValidation.IsValid
时,您可以手动启动整个对象图的子复杂对象验证,依此类推。作为奖励,您可以通过CompositeValidationResult
收集所有错误
i、 e
使用系统;
使用System.ComponentModel.DataAnnotations;
使用System.Collections.Generic;
公共课程
{
公共静态void Main(){
var person=新的人{
地址=新地址{
城市=“小镇”,
State=“TX”,
Zip=新的ZipCode()
},
Name=“肯特”
};
var context=新的ValidationContext(person,null,null);
var results=新列表();
TryValidateObject(person、context、results、true);
打印结果(结果,0);
Console.ReadKey();
}
私有静态void打印结果(IEnumerable结果,Int32缩进级别){
foreach(结果中的var validationResult){
Console.WriteLine(validationResult.ErrorMessage);
Console.WriteLine();
如果(validationResult为CompositeValidationResult){
打印结果(((CompositeValidationResult)validationResult)。结果,缩进级别+1);
}
}
}
}
公共类ValidateObject属性:ValidationAttribute{
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext){
var results=新列表();
var context=newvalidationcontext(值,null,null);
TryValidateObject(值、上下文、结果、true);
如果(results.Count!=0){
var compositeResults=new CompositeValidationResult(String.Format(“验证{0}失败!”,validationContext.DisplayName));
results.ForEach(compositeResults.AddResult);
返回合成结果;
}
返回ValidationResult.Success;
}
}
公共类CompositeValidationResult:ValidationResult{
私有只读列表_results=new List();
可数结果{
得到{
返回结果;
}
}
公共CompositeValidationResult(字符串errorMessage):基(errorMessage){}
公共CompositeValidationResult(字符串errorMessage,IEnumerable memberNames):基(errorMessage,memberNames){}
受保护的CompositeValidationResult(ValidationResult ValidationResult):基(ValidationResult){}
public void AddResult(ValidationResult ValidationResult){
_结果。添加(validationResult);
}
}
公共阶层人士{
[必需]
公共字符串名称{get;set;}
[必需,验证对象]
公共广播地址{get;set;}
}
公共课堂演讲{
[必需]
公共字符串Street1{get;set;}
公共字符串Street2{get;set;}
[必需]
公共字符串City{get;set;}
[必需]
公共字符串状态{get;set;}
[必需,验证对象]
公共ZipCode Zip{get;set;}
}
公共类ZipCode{
[必需]
公共字符串主代码{get;set;}
公共字符串子代码{get;set;}
}
我希望在TitleAuthorAndPublishingConfiguration
的属性上使用数据注释验证器来引用TitleAuthorAndPublishingConfiguration
的另一个属性。但是,DB.SaveChanges()
并不是直接在这个类上调用的,而是在它的父级-WebsiteConfiguration
上调用的,希望澄清一下,您是否拥有标题author and publishingconfiguration
验证程序?我在问题中添加了验证程序代码-这就是您的意思吗?谢谢。我要试一试。