Prevent saving properties in sitecore with custom validator in C#

less than a minute read

Recently I had a requirement that when under certain conditions a Sitecore field should become readonly. To accomplish this requirement I created a new ReadOnlyWhenXYZValidator. The requirement stated that the validator should stop a user from saving the item if the field had changed. Here is how I accomplished it.

What I decided to do was create a custom validator that can be applied to each property that should become readonly once a condition is met.

[Serializable]
public class ReadOnlyWhenXYZValidator : StandardValidator
{
    public ReadOnlyWhenXYZValidator()
        : base()
    {
    }

    public ReadOnlyWhenXYZValidator(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }

    public override string Name
    {
        get { 
            return Sitecore.StringUtil.GetString(this.Parameters["ValidatorName"], 
                                                 this.GetType().ToString()); }
    }

    protected override ValidatorResult GetMaxValidatorResult()
    {
        return GetFailedResult(ValidatorResult.Error);
    }

    protected override ValidatorResult Evaluate()
    {
        Item item = this.GetItem();
        // The following will need to be replaced with your own logic to 
        // retrieve if an item should be readonly...
        var isReadOnly= ShouldBeReadOnly(item.ID.Guid);
        if (isReadOnly)
        {
            bool propertyHasChanged = HasPropertyChanged();
            if (propertyHasChanged)
            {
                this.Text = String.Format(
                   "Field '{0}' is readonly and cannot be updated",
                   this.GetFieldDisplayName());
                   
                // Fatal Error is required in order to prevent saving
                return ValidatorResult.FatalError;
            }  
        }
        this.Text = "Valid";
        return ValidatorResult.Valid;
    }

    /// <summary>
    /// Returns a value indicating if the property value has changed
    /// </summary>
    private bool HasPropertyChanged()
    {
        var value = GetControlValidationValue();
        var contentItem = Sitecore.Context.ContentDatabase.GetItem(GetItem().ID);
        if (contentItem == null)
        {
            return false;
        }

        var oldValue = contentItem[GetField().ID];
        //Check if current value is different from an old value
        return value != oldValue;
    }
}

Notice I am returning a ValidatorResult.FatalError. This is the only ValidatorResult that prevents a user from saving an item, so although it sounds over the top, is required.

Once complete, simply tell Sitecore to run the validator against the fields you wish to validate. This is done by firstly adding a new Validation Rule to System > Settings > Validation Rules > Field Rules or a sub folder of that.

Once added, simply navigate to your field definitions and, within the Validation Rules section, add your custom validator to each of the folllowing:

  • Quick Action Bar
  • Validate Button
  • Validator Bar
  • Workflow

Once complete load your items and you should find you can't save items that match the condition you have. I hope this helps. Don't forget to share this article if you found it helpful.


Comments
pravinkumar says:April 3, 2014

I have tried this but data is saving. I want that when validation give error than data should not save. It should be abort save state.

John says:April 3, 2014

Hi Pravinkumar,

Providing the validator is returning ValidatorResult.FatalError then sitecore determines that this will prevent saving. Could it be possible that the result is not a FatalError.

pravinkumar says:April 3, 2014

Thanks John: I have solve first problem. One more point is that . I want to get new value of field in class file EX : Suppose I have on date filed . I am going to change from 03 Apr to 05 Apr . in that case i want to get 05 Apr value in my class file. It is possible

I have used Item validation.

I am trying to compare start date and end date field validation .

Pls help me if possible

thanks you in advance

John says:April 3, 2014

Hi Pravinkumar,

Glad to help. You can use GetControlValidationValue(); to get the new value that has been set (05 Apr). For reference, take a look at the HasPropertyChanged() method above.

pravinkumar says:April 4, 2014

Hi John : I already used you technique. but problem is that. I got null value. Here I want to two filed (new value) StartDate and EndDate. then after I will compare both.

------------------ Example -----------------

Sitecore.Data.Items.Item item = this.GetItem(); string firstFieldName = Sitecore.StringUtil.GetString(this.Parameters["FirstFieldName"], "StartDate"); string lastFieldName = Sitecore.StringUtil.GetString(this.Parameters["LastFieldName"], "EndDate"); Sitecore.Data.Fields.DateField first = item.Fields[firstFieldName]; Sitecore.Data.Fields.DateField last = item.Fields[lastFieldName];

        here I have got old value 
        
        I want New updated value which is not saved in DB
        
        
        
John says:April 4, 2014

Hi Pravinkumar,

This particular validator is not able to validate other pre-saved field values unfortunately.

pravinkumar says:April 4, 2014

ok Many Many thnxxx

Kyle says:August 4, 2014

John, do you know how to display some sort of message on the dialog that prevents users from saving the message in the content editor? "This item contains fields with fatal errors." isn't super helpful.