Write custom attributes to improve the editor experience, add business rules, or add custom validation.
Restricting 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 IMetadataAware for your attribute to add metadata that affects the editing experience of the property.
You can combine the implementation of the IMetadataAware 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 through an attribute:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace EPiServer.Samples
{
public class PropertyEditRestrictionAttribute : ValidationAttribute, IMetadataAware
{
public PropertyEditRestrictionAttribute(string[] allowedRoles)
{
AllowedRoles = allowedRoles;
}
public string[] AllowedRoles { get; set; }
public void OnMetadataCreated(ModelMetadata metadata)
{
foreach (string role in AllowedRoles)
{
if (EPiServer.Security.PrincipalInfo.CurrentPrincipal.IsInRole(role))
{
return;
}
}
metadata.IsReadOnly = true;
}
}
}
Usage on the model should look as follows. The example uses the group name administrators2 to make sure you are not member of this group.
[PropertyEditRestriction(new string[]{"administrators2"})]
public virtual XhtmlString MainBody { get; set; }
Go to the Episerver edit view to see that the editor was disabled in the All properties editing view:
In the On-page editing view, the property looks editable, but if you cannot edit the property and you click on the overlay, edit view loads a read-only editor and removes the overlay entirely.
Validation on the server
The following example adds server validation to the same attribute from the example in the previous section, so that you cannot post a fake property update to the server even without having the correct access.
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using EPiServer.Core;
namespace EPiServer.Samples
{
public class PropertyEditRestrictionAttribute : ValidationAttribute, IMetadataAware
{
public PropertyEditRestrictionAttribute(string[] allowedRoles)
{
AllowedRoles = allowedRoles;
}
public string[] AllowedRoles { get; set; }
public void OnMetadataCreated(ModelMetadata metadata)
{
foreach (string role in AllowedRoles)
{
if (EPiServer.Security.PrincipalInfo.CurrentPrincipal.IsInRole(role))
{
return;
}
}
//Comment row below to test the server validation.
metadata.IsReadOnly = true;
}
public override string FormatErrorMessage(string name)
{
return "You do not have access to change " + name;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var contentData = validationContext.ObjectInstance as IContentData;
if (contentData == null)
{
//This attribute only handles instances of IContentData. return ValidationResult.Success;
}
if (!contentData.Property[validationContext.MemberName].IsModified)
{
return ValidationResult.Success;
}
if (Validate())
{
return ValidationResult.Success;
}
else { return new ValidationResult("You do not have access"); }
}
public override bool RequiresValidationContext
{
get
{
return true;
}
}
public bool Validate()
{
foreach (string role in AllowedRoles)
{
if (EPiServer.Security.PrincipalInfo.CurrentPrincipal.IsInRole(role))
{
return true;
}
}
return false;
}
}
}
You can comment out the line that makes the property read-only, and edit the property to validate that the server validation actually does work.
Last updated: May 26, 2021