Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Write custom attributes

Describes how to write custom attributes to improve the editor experience, add business rules, or add custom validation.

Restrict access for editing a certain property

You can restrict access in the following ways:

  • Create a ValidationAttribute to add server-side validation when data is saved.
  • Implement IDisplayMetadataProvider for your attribute to add metadata that affects the editing experience of the property.

You can combine the implementation of the IDisplayMetadataProvider attribute with a ValidationAttribute to control which roles can edit a specific property.

The following example shows how to make a property read-only in the editorial interface and adds server-side validation if the content is changed outside the editorial interface through an attribute:

using EPiServer.Core;
using EPiServer.Security;
using EPiServer.Shell.ObjectEditing;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace EPiServer.Samples {
  public class PropertyEditRestrictionAttribute: ValidationAttribute, IDisplayMetadataProvider {
    public PropertyEditRestrictionAttribute(string[] allowedRoles) {
      AllowedRoles = allowedRoles;
    }

    public string[] AllowedRoles {
      get;
      set;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
      if (validationContext.ObjectInstance is IContentData content) {
        if (!content.Property[validationContext.MemberName].IsModified) {
          return ValidationResult.Success;
        }

        return IsInRole ? ValidationResult.Success : new ValidationResult("You do not have access");
      }

      //This attribute only handles instances of IContentData. return ValidationResult.Success;
      return ValidationResult.Success;
    }

    public void CreateDisplayMetadata(DisplayMetadataProviderContext context) {
      if (IsInRole) {
        return;
      }

      var extendedMetadata = context.DisplayMetadata.AdditionalValues[ExtendedMetadata.ExtendedMetadataDisplayKey] as ExtendedMetadata;
      if (extendedMetadata == null) {
        return;
      }
      extendedMetadata.IsReadOnly = true;
    }

    private bool IsInRole => AllowedRoles.Any(r => PrincipalInfo.CurrentPrincipal.IsInRole(r));

  }
}

Usage on the model should look as follows. The example uses the group name administrators2 to ensure you are not a member of this group.

[PropertyEditRestriction(new string[] {
  "administrators2"
})]
public virtual XhtmlString MainBody {
  get;
  set;
}

Go to the Optimizely edit view to see that the editor was disabled in the All Properties editing view:

Optimizely edit view shows that the editor was disabled in the **All Properties** editing view

In the On-page editing view, the property looks editable. Still, if you cannot edit the property and click on the overlay, edit view loads a read-only editor and removes the overlay entirely.

the property looks editable

Validate the server

The example above adds server validation to the same attribute from the example in the previous section, so you cannot post a fake property update to the server without the correct access.

You can comment out the line that makes the property read-only and edit the property to validate that the server validation works.