BlockType属性条件验证咨询:仅DisplayPdfButton为真时必填DownloadPdfText
Absolutely, this is totally achievable! Since you're working with EPiServer (I can tell from the TabNames reference), here are a couple of robust approaches to implement this conditional required validation for your Block Type:
Approach 1: Custom Validation Attribute
Create a reusable custom validation attribute that checks the value of a dependent property before enforcing required validation on your target property.
Step 1: Implement the Custom Attribute
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ConditionalRequiredAttribute : ValidationAttribute { // Name of the property we're checking against public string DependentProperty { get; set; } // The value the dependent property needs to match to trigger required validation public object TargetValue { get; set; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Get the dependent property from the Block Type var dependentProperty = validationContext.ObjectType.GetProperty(DependentProperty); if (dependentProperty == null) { return new ValidationResult($"Could not find dependent property: {DependentProperty}"); } // Get the current value of the dependent property var dependentValue = dependentProperty.GetValue(validationContext.ObjectInstance, null); // If the dependent property matches our target value AND the target property is empty, return an error if (Equals(dependentValue, TargetValue) && (value == null || string.IsNullOrWhiteSpace(value.ToString()))) { return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } // Validation passes return ValidationResult.Success; } }
Step 2: Update Your Block Type
Replace the [Required] attribute on DownloadPdfText with your new custom attribute, pointing to the DisplayPdfButton property:
[CultureSpecific] [Display(Name = "Display PDF Button", GroupName = TabNames.PDFCustomisation, Order = 0)] public virtual bool DisplayPdfButton { get; set; } [CultureSpecific] [ConditionalRequired( DependentProperty = nameof(DisplayPdfButton), TargetValue = true, ErrorMessage = "Download Pdf Text is required when Display PDF Button is enabled.")] [Display(Name = "Download Pdf Text", GroupName = TabNames.PDFCustomisation, Order = 1)] public virtual string DownloadPdfText { get; set; }
Approach 2: EPiServer IValidate Interface
EPiServer has a built-in validation interface IValidate<T> that's perfect for type-specific validation logic. This is often preferred for more complex scenarios, as it keeps validation logic separate from your model.
Step 1: Create the Validator Class
public class PdfBlockValidator : IValidate<YourBlockTypeName> { public IEnumerable<ValidationError> Validate(YourBlockTypeName instance) { // Check if the PDF button is enabled and the text is empty if (instance.DisplayPdfButton && string.IsNullOrWhiteSpace(instance.DownloadPdfText)) { yield return new ValidationError { PropertyName = nameof(YourBlockTypeName.DownloadPdfText), ErrorMessage = "Download Pdf Text is required when Display PDF Button is checked.", Severity = ValidationErrorSeverity.Error }; } } }
Make sure to replace YourBlockTypeName with the actual name of your Block Type.
Step 2: Register the Validator
EPiServer will automatically discover this validator if it's in a scanned assembly. If not, you can register it via dependency injection:
services.AddTransient<IValidate<YourBlockTypeName>, PdfBlockValidator>();
Bonus: Client-Side Validation
For a better editor experience, add client-side validation to enforce the rule immediately when the checkbox is toggled. Add this script to your Block's edit view:
$(document).ready(function() { const displayCheckbox = $('#DisplayPdfButton'); const downloadTextInput = $('#DownloadPdfText'); function updateRequiredState() { if (displayCheckbox.is(':checked')) { downloadTextInput.attr('required', 'required'); } else { downloadTextInput.removeAttr('required'); // Clear any existing validation errors for this field downloadTextInput.removeClass('input-validation-error'); $('#DownloadPdfText-error').remove(); } } // Set initial state on page load updateRequiredState(); // Update state when checkbox is toggled displayCheckbox.change(updateRequiredState); });
Both approaches will ensure that DownloadPdfText is only required when DisplayPdfButton is set to true. Choose the one that fits best with your project's structure!
内容的提问来源于stack exchange,提问作者Ayo Adesina

