How not to
The quick and dirty way is just to add a required attribute (and if you are a bit interested in your editor you will add an error message). But that will generate a horrible first page where editors must add the required values before creating the page.
The image represents the interface the editor experienced before the block is created
How it should be done
I like to do one validator for each model I have. Here I can send out all my messages to the editor. I send out warnings and all my validation here. So, all fields on the page can be added on the same page. If one property depends on another property - tell the editor!
Here is a simple tutorial on how to validate your model
[ContentType(GUID = "740EB686-2DDD-4AD4-A8CF-615D3389DE6B")]
[SiteImageUrl]
public class LinksTutorialBlock : BlockData
{
[CultureSpecific]
[Display(Order = 100)]
[UIHint(UIHint.MediaFile)]
public virtual ContentReference? Link { get; set; }
[CultureSpecific]
[Display(Order = 200)]
public virtual string? FileExtension { get; set; }
[CultureSpecific]
[Display(Order = 300)]
[UIHint(UIHint.MediaFile)]
public virtual ContentReference? SecondLink { get; set; }
[CultureSpecific]
[Display(Order = 400)]
public virtual string? SecondFileExtension { get; set; }
}
And here is some examples of how to validate your model
public class LinksTutorialBlockValidator : IValidate<LinksTutorialBlock>
{
public IEnumerable<ValidationError> Validate(LinksTutorialBlock block)
{
if (block.FirstLink == null)
{
yield return new ValidationError
{
ErrorMessage = "Add first link",
Severity = ValidationErrorSeverity.Error,
ValidationType = ValidationErrorType.PropertyValidation
};
}
if (block.FirstLink != null && block.SecondLink != null)
{
if (string.IsNullOrEmpty(block.FirstFileExtension) || string.IsNullOrEmpty(block.SecondFileExtension))
{
yield return new ValidationError
{
ErrorMessage =
"Add file extension for both links.",
Severity = ValidationErrorSeverity.Warning,
ValidationType = ValidationErrorType.PropertyValidation
};
}
}
if (block.SecondLink != null && block.FirstLink == null)
{
yield return new ValidationError
{
ErrorMessage = "Secondary link will not be displayed without first link",
Severity = ValidationErrorSeverity.Error,
ValidationType = ValidationErrorType.PropertyValidation
};
}
const string pattern = "^[a-z|0-9]{0,4}$";
if ((block.FirstFileExtension != null && !Regex.IsMatch(block.FirstFileExtension, pattern)) || (block.SecondFileExtension != null && !Regex.IsMatch(block.SecondFileExtension, pattern)))
{
yield return new ValidationError
{
ErrorMessage = "File extensions can only contain letters and numbers and can only contain 4 characters" ,
Severity = ValidationErrorSeverity.Error,
ValidationType = ValidationErrorType.PropertyValidation
};
}
}
I don't question that you have seen the IValidate before. But do use it more than before. If you keep this in mind, you don't need to answer questions down the road about how everything works.