In my Caliburn Bootstrapper, I am trying to validate that a user has permissions to run my application. If they do not, I need to present them with a message and exit. The following code throws a NullReferenceException on the MessageBox.Show() call. Even if I move the ComposeMef() call before the ValidateUserHasPermissionsToRun() in the Configure() method, it still errors.
public class MyBootstrapper : Bootstrapper<DropWindowViewModel>
{
// irrelevant methods omitted for brevity
protected override void Configure()
{
this.InitializeSecurity();
this.ValidateUserHasPermissionToRun();
this.ComposeMef();
}
private void ComposeMef()
{
AggregateCatalog catalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
this.container = new CompositionContainer(catalog);
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(this.container);
batch.AddExportedValue(catalog);
this.container.Compose(batch);
}
private void ValidateUserHasPermissionToRun()
{
User user = SecurityContext.Current.SecurityUser;
if (!user.HasPrivilege(Constants.PrivilegeLoadData))
{
// throws an exception
MessageBox.Show("You do not have access to VIPER. Please contact the help desk if you need help.");
this.TerminateApplication();
}
}
}
What is the proper way to handle this? For something this simple, I just want to show a message box. I don’t really want to get into composing a whole new ViewModel/View. If I have to use a different ViewModel, how would I switch which ViewModel Caliburn uses? Or should I set a property on the DropWindowViewModel to trigger a different interface?
I’d suggest this is something that should be done within your root viewmodel. The bootstrapper should be just that. It loads the resources needed for your app & configures them. After that it’s done. Checking whether the user can run the app is part of your application logic & should therefore go in the root viewmodel.