gpt4 book ai didi

asp.net-mvc - 如何在数据库实体的子模型上使用自定义验证属性?

转载 作者:行者123 更新时间:2023-12-04 01:13:23 25 4
gpt4 key购买 nike

摘要:

我想要一个数据注释验证器来引用同一类中的另一个属性 ( TitleAuthorAndPublishingConfiguration )。

但是,不会直接在此类上调用 DB.SaveChanges()。而是在此类的父级 ( WebsiteConfiguration ) 上调用它。

因此 validationContext.ObjectType正在返回 WebsiteConfiguration我无法引用 TitleAuthorAndPublishingConfiguration 的属性在数据注释验证器中。

网站配置.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...

ApplicationDbContext.cs
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;
}
}

问题
  • 有没有办法让我从 validationContext 访问子模型属性?
  • 我的方法是否被误导了?有没有更好的方法将多个模型作为更大模型的一部分存储在单个数据库表中?

  • 我希望不要有多个配置表和对数据库的调用。 (本例中有 4 个子模型,但下一个应用程序中可能有 10 个以上。)

    上面的设置在很多方面满足了我的需求。但是我不想放弃子模型上DataAnnotations的功能!

    奖金问题

    我遇到过一些这样的帖子:
    How can I tell the Data Annotations validator to also validate complex child properties?

    但那是 4 岁,我想知道从那时起是否有任何变化。

    我是否正在尝试做一些基本上不可能(或至少非常困难)的事情?

    最佳答案

    Am I trying to do something that is basically impossible (or at least very difficult)?



    不,有一个非常简单的解决方案,可以与使用 DataAnnotations 的框架和技术完美集成。

    您可以创建自定义 ValidationAttribute由 EF 验证调用并调用 Validator.TryValidateObject里面。这样,当 CustomValidation.IsValid由 EF 调用,您手动启动子复杂对象验证,依此类推整个对象图。作为奖励,您可以通过 CompositeValidationResult 收集所有错误。 .

    IE。
    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Collections.Generic;

    public class Program
    {
    public static void Main() {
    var person = new Person {
    Address = new Address {
    City = "SmallVille",
    State = "TX",
    Zip = new ZipCode()
    },
    Name = "Kent"
    };

    var context = new ValidationContext(person, null, null);
    var results = new List<ValidationResult>();

    Validator.TryValidateObject(person, context, results, true);

    PrintResults(results, 0);

    Console.ReadKey();
    }

    private static void PrintResults(IEnumerable<ValidationResult> results, Int32 indentationLevel) {
    foreach (var validationResult in results) {
    Console.WriteLine(validationResult.ErrorMessage);
    Console.WriteLine();

    if (validationResult is CompositeValidationResult) {
    PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);
    }
    }
    }

    }

    public class ValidateObjectAttribute: ValidationAttribute {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
    var results = new List<ValidationResult>();
    var context = new ValidationContext(value, null, null);

    Validator.TryValidateObject(value, context, results, true);

    if (results.Count != 0) {
    var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));
    results.ForEach(compositeResults.AddResult);

    return compositeResults;
    }

    return ValidationResult.Success;
    }
    }

    public class CompositeValidationResult: ValidationResult {
    private readonly List<ValidationResult> _results = new List<ValidationResult>();

    public IEnumerable<ValidationResult> Results {
    get {
    return _results;
    }
    }

    public CompositeValidationResult(string errorMessage) : base(errorMessage) {}
    public CompositeValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames) {}
    protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}

    public void AddResult(ValidationResult validationResult) {
    _results.Add(validationResult);
    }
    }

    public class Person {
    [Required]
    public String Name { get; set; }

    [Required, ValidateObject]
    public Address Address { get; set; }
    }

    public class Address {
    [Required]
    public String Street1 { get; set; }

    public String Street2 { get; set; }

    [Required]
    public String City { get; set; }

    [Required]
    public String State { get; set; }

    [Required, ValidateObject]
    public ZipCode Zip { get; set; }
    }

    public class ZipCode {
    [Required]
    public String PrimaryCode { get; set; }

    public String SubCode { get; set; }
    }

    关于asp.net-mvc - 如何在数据库实体的子模型上使用自定义验证属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33489735/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com