Authorization Sample 304 – MVVM Authorization for Silverlight
In Authorization Sample 301 I explained the ins-and-outs of the authorization sample and offered a few hints as to how it could be used. In this post, I will show a specific example where I put together an authorized form using the Model-View-ViewModel pattern.
For this form, I created a simple view model with the following properties.
public class ViewModel : INotifyPropertyChanged
{
public int Id { get; set; }
public ModelValue Value { get; set; }
public Visibility ValueVisibility { get; private set; }
public string Text { get; set; }
public Visibility TextVisibility { get; private set; }
public bool IsTextReadOnly { get; private set; }
public ICommand ResetCommand { get; }
}
My goal was to present a customized view for each user role. To implement this I created a couple AuthorizationSources using AuthorizationAttributes. The benefit of using sourcesis they subscribe to user changes and apply the attributes to provide an AuthorizationResult that I can bind to in my view model. The _memberSource tells me if the user is a “member”, and the _administratorSource tells me if the user is an “administrator”.
public ViewModel()
{
this._memberSource =
new AuthorizationSource(
new[] { new RequiresRoleAttribute("member") });
this._administratorSource =
new AuthorizationSource(
new[] { new RequiresRoleAttribute("administrator") });
this._resetCommand = new AuthorizationCommand(
this._administratorSource,
new ResetCommand(this));
this._memberSource.PropertyChanged +=
(s, e) => this.CalculateAuthorizedProperties();
this._administratorSource.PropertyChanged +=
(s, e) => this.CalculateAuthorizedProperties();
this.CalculateAuthorizedProperties();
}
The CalculateAuthorizedProperties method takes the results from each source and uses them to set other view model properties that I’ve bound to in my view.
private void CalculateAuthorizedProperties()
{
this.ValueVisibility =
(this._memberSource.Result == AuthorizationResult.Allowed) ?
Visibility.Visible :
Visibility.Collapsed;
this.TextVisibility = this.ValueVisibility;
this.IsTextReadOnly =
(this._administratorSource.Result != AuthorizationResult.Allowed);
}
The last bit of the sample to highlight is the _resetCommand. An AuthorizationCommand is created taking an AuthorizationSource and a command to delegate to. When the result on the source is not equal to AuthorizationResult.Allowed, the command’s CanExecute property will be set to false. When the authorization command is allowed, it will delegate to other command passed in to its constructor.
I’ve included the source for the sample here.
In this sample I stuck mostly to AuthorizationAttributes and AuthorizationSources. These are definitely the most interesting types for MVVM authorization, but AuthorizationRules might also prove helpful. For instance, for complex logic like interpreting metadata on an Entity a rule could be used to determine which attributes to pass to the source. That would make the logic both encapsulated and reusable for multiple view models.