3

We are developing a workflow-like application. We want to display the same form (with the same ViewModel and the same View) for different user roles. We want to make some fields ReadOnly Not Editable based on specific user roles.

The ViewModel would be like:

public class ServiceViewModel
{
    [EditableIfInRoles("Administrator", "Editor")]
    public string ServiceId { get; set; }
}

We are planing to create a custom ReadOnlyAttribute, like:

public class EditableIfInRolesAttribute : EditableAttribute
{
    private IEnumerable<string> _allowedRoles; 

    public EditableIfInRolesAttribute(params string[] allowedRoles) : base(true)
    {
        _allowedRoles = allowedRoles;
    }

    /// <summary>
    /// Currently we don't know which method to override
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public override bool IsEditable(object value)
    {
        return _allowedRoles.Any(e => HttpContext.Current.User.IsInRole(e));
    }
}

The rendered HTML that we expect for unauthorized user roles is:

<input class="form-control global" id="ServiceID" name="ServiceID" type="text" value="" readonly="readonly">

How to create a custom attribute that inherits either ReadOnlyAttribute or 'EditableAttribute', since both of them are sealed class?

What method to override? Or is there any other solution?

Thanks.

gusdewa
  • 111
  • 1
  • 3
  • 10

1 Answers1

2

Your misunderstanding the usage of EditableAttribute It has no affect on the html generated by html helpers. All it does is set the IsReadOnly property of the ModelMetaData. You could of course read the value using something like

@if (ViewData.ModelMetadata.Properties.Where(p => p.PropertyName == "SomeProperty").First().IsReadOnly)
{
  // add the readonly="readonly" attribute to the control

but this is not the intended usage.

Some options include

  1. Setting a view model or ViewBag property (say bool isReadOnly) and then adding the html readonly attribute based on on the value. An example of this approach is shown in this answer
  2. Create your own html helpers that accept a view model or ViewBag property. An example of this approach is shown in this answer
  3. If you want to use DataAnnotations, create you own attribute that inherits Attribute and implements IMetadataAware and then create your own html helpers that read the attributes properties and add the html attributes. An example of this approach is shown in this answer
Community
  • 1
  • 1