Best practice for content validation with IValidate<T> and IContentSaveValidate<T>

Vote:
 

Update: Fixed content error (original in strikethrough)

Hey guys,

I am seeking advice on how to best implement custom validation logic on a custom page content instance (but the same may apply to all other content data as well I think). The documentation section Validate object instances (optimizely.com) list two main hooks that can be used for this: IValidate<T> and IContentSaveValidate<T>

My environment:

  • EPiServer CMS 11.x
  • Auto-save in CMS is enabled, so save events are periodically fired when changes to properties are noticed by the application.

My goal:

Ideally I would like to prevent the save from being commited to the data store, but my experiments have shown that this is easier said than done. This leads me to the questions that emerged when experimenting with the validation infrastructure.

My questions:

  1. Implementing IValidate<T> let's the validator run every time an instance of T is saved. Any validation errors do not prevent the instance from being saved, but prevent it from being saved published. Is there any way to configure this behaviour to cancel the save operation?
  2. I know that you can hook into the content events, e.g SavingContent, SavedContent etc. However I have not found a way to access validation results there. I could manually run validation again by calling the IValidationService.Validate method, but this would execute validation two times. First one triggered by the framework, second one triggered manually. Is there any suggested way to better hook into this process?
  3. I have observed that implementations of IContentSaveValidate<T> are not triggered automatically on content saving, but on content publishing. What is the reasoning behind this? The example at IContentSaveValidate - validation with context | Optimizely Devel suggest that this interface is useful during all state transitions, but it seems to be only called on publishing. Is there any suggested way of calling this interface manually?

Best regards,
Sebastian

#313503
Edited, Dec 01, 2023 9:42
Vote:
 

IValidate would return a list of ValidationError, if your implementation returns a list that contains an error, like this 

return new List<ValidationError> {new ValidationError()
{
    PropertyName = //property name,
    Severity = ValidationErrorSeverity.Error,
    ValidationType = ValidationErrorType.StorageValidation,
    ErrorMessage = errorMessage
}};

that would cancel the save. I am not quite sure if the data is saved to draft or not, probably not, but you can try

#313505
Dec 01, 2023 10:33
Vote:
 

Hi Quan,

thanks for the quick reply! 

Unfortunately that is not the case as far as I can see. I am currently running version 11.20.14 of EpiServer. The following behaviour can be observed:

  1. Save a page which value that produces >= 1 ValidationError in IValidate<T>
  2. Validater is called
  3. Saving event is raised
  4. Saved event is raised
  5. UI displays validation error (next to publish button)
  6. When reloading the page the invalid value is shown indicating that the value was indeed saved.
#313508
Dec 01, 2023 12:25
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.