diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadService.h b/openbis-ipad/BisKit/Classes/CISDOBIpadService.h
index bd5632dd6af24d571cbeb5a0caa8265be386a288..bcfc8517360c95e63a8f613b3f261da19751901a 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadService.h
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadService.h
@@ -59,8 +59,8 @@ enum CISOBIpadServiceErrorCode {
 //! Get all top-level categories from the openBIS ipad service. The success block will be invoked with a collection of CISDOBIpadRawEntity objects.
 - (CISDOBAsyncCall *)listNavigationalEntities;
 
-//! Get all root-level entities from the openBIS ipad service, possibly along with some children as well. The success block will be invoked with a collection of CISDOBIpadRawEntity objects.
-- (CISDOBAsyncCall *)listRootLevelEntities;
+//! Get all root-level entities from the openBIS ipad service for the specified navigational entities. This should return all the entities associated with that navigational entity that are considered part of the root set. The success block will be invoked with a collection of CISDOBIpadRawEntity objects.
+- (CISDOBAsyncCall *)listRootLevelEntities:(NSArray *)permIds refcons:(NSArray *)refcons;
 
 //! Get drill information from the openBIS ipad service -- this will include information about the children of the entity and possibly their children as well. The permIds and refcons collections must have the same cardinality. The success block will be invoked with a collection of CISDOBIpadRawEntity objects.
 - (CISDOBAsyncCall *)drillOnEntities:(NSArray *)permIds refcons:(NSArray *)refcons;
diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadService.m b/openbis-ipad/BisKit/Classes/CISDOBIpadService.m
index d219906939bcab4af6621cd11ef51f396253e20d..213d911818c7cb32a3c3745536fc15b55daf18a6 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadService.m
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadService.m
@@ -154,9 +154,16 @@ static id OpenBisTableRowValueAtIndex(NSArray *rowData, NSUInteger index)
     return serviceCall;
 }
 
-- (CISDOBAsyncCall *)listRootLevelEntities
+- (CISDOBAsyncCall *)listRootLevelEntities:(NSArray *)permIds refcons:(NSArray *)refcons
 {
-    NSDictionary *parameters = [NSDictionary dictionaryWithObject: @"ROOT" forKey: @"requestKey"];
+    NSUInteger count = [permIds count];
+    NSAssert([refcons count] == count, @"Drilling requires permIds and refcons. There must be an equal number of these.");
+    NSArray *entities;
+    entities = [self convertToEntitiesPermIds: permIds refcons: refcons count: count];
+    NSDictionary *parameters =
+        [NSDictionary dictionaryWithObjectsAndKeys:
+            @"ROOT", @"requestKey",
+            entities, @"entities", nil];
     CISDOBIpadServiceCall *serviceCall = [self createIpadServiceCallWithParameters: parameters];
     // Make sure the timeout interval is at least 60s
     if (serviceCall.timeoutInterval < 60.) serviceCall.timeoutInterval = 60.;
diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
index 0b24b469adc46738bd1ee7c56e9968190a59129f..55c964825ce3bb8a5035cc0203557cc810773c16 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
@@ -86,7 +86,7 @@ typedef void (^MocSaveBlock)(CISDOBIpadServiceManager *serviceManager, NSArray *
 @property (readonly) NSString *sessionToken;
 @property (nonatomic, getter=isOnline) BOOL online;
 
-@property(strong, nonatomic) NSDate *lastRootSetUpdate;
+@property(strong, nonatomic) NSDate *lastRootSetUpdateDate;
 
 //! Called when the service encounters an authentication challenge
 @property (copy, nonatomic) AuthenticationChallengeBlock authenticationChallengeBlock;
diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
index 80694260b72b7486e18af5ab5869b87912b55924..5da9c7610ea17de4f3f8ad2dcce8af67922da809 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
@@ -45,13 +45,14 @@ NSString *const CISDOBIpadServiceManagerErrorDomain = @"CISDOBIpadServiceManager
 // Internal class that synchronizes result data to the managed object context
 @interface CISDOBBackgroundDataSynchronizer : NSObject
 
-@property(readonly, weak) CISDOBIpadServiceManager *serviceManager;
-@property(readonly, strong) CISDOBIpadServiceManagerCall *managerCall;
-@property(readonly, strong) NSArray *rawEntities;
-@property(readonly, strong) NSManagedObjectContext *managedObjectContext;
-@property(nonatomic, copy) NSError *error;
+@property(weak, readonly) CISDOBIpadServiceManager *serviceManager;
+@property(strong, readonly) CISDOBIpadServiceManagerCall *managerCall;
+@property(strong, readonly) NSArray *rawEntities;
+@property(strong, readonly) NSManagedObjectContext *managedObjectContext;
+@property(copy, nonatomic) NSError *error;
 
 @property(nonatomic) BOOL prune;
+@property(strong, nonatomic) NSDate *pruneCutoffDate;
 @property(readonly) NSArray *deletedEntities;
 
 // Initialization
@@ -63,6 +64,27 @@ NSString *const CISDOBIpadServiceManagerErrorDomain = @"CISDOBIpadServiceManager
 
 @end
 
+// This class is not yet used, but is a sketch for seperating updates from pruning
+@interface CISDOBBackgroundDataPruner : NSObject
+
+@property(weak, readonly) CISDOBIpadServiceManager *serviceManager;
+@property(strong, readonly) CISDOBIpadServiceManagerCall *managerCall;
+@property(strong, readonly) NSManagedObjectContext *managedObjectContext;
+@property(copy, nonatomic) NSError *error;
+
+@property(nonatomic) BOOL prune;
+@property(strong, nonatomic) NSDate *pruneCutoffDate;
+@property(readonly) NSArray *deletedEntities;
+
+// Initialization
+- (id)initWithServiceManager:(CISDOBIpadServiceManager *)serviceManager;
+
+// Actions
+- (void)run;
+- (void)notifyCallOfResult;
+
+@end
+
 static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl, NSError** error)
 {
 	// Explicitly specify which db schema we want to use
@@ -145,6 +167,7 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
         // Run the synchronizer in the background thread
         CISDOBBackgroundDataSynchronizer *synchronizer = [[CISDOBBackgroundDataSynchronizer alloc] initWithServiceManager: self managerCall: managerCall rawEntities: rawEntities];
         synchronizer.prune = prune;
+        synchronizer.pruneCutoffDate = self.lastRootSetUpdateDate;
         [synchronizer run];
         
         [[NSNotificationCenter defaultCenter] postNotificationName: CISDOBIpadServiceDidSynchEntitiesNotification object: self];         
@@ -201,20 +224,10 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
     [call start];
 }
 
-- (CISDOBIpadServiceManagerCall *)managerCallWrappingServiceCall:(CISDOBAsyncCall *)serviceCall pruning:(BOOL)prune
+- (void)initializeFailureBlockOnServiceCall:(CISDOBAsyncCall *)serviceCall managerCall:(CISDOBIpadServiceManagerCall *)managerCall
 {
-    CISDOBIpadServiceManagerCall *managerCall = [[CISDOBIpadServiceManagerCall alloc] initWithServiceManager: self serviceCall: serviceCall];
-    
     __weak CISDOBIpadServiceManager *weakSelf = self;
     
-    serviceCall.success = ^(id result) {
-        weakSelf.online = YES;
-        // We treat prune as a synonym for the root set update call
-        if (prune) weakSelf.lastRootSetUpdate = [NSDate date];
-        // Update the cache and call the managerCall success when done
-        [weakSelf syncEntities: result pruning: prune notifying: managerCall];
-    };    
-    
     serviceCall.fail = ^(NSError *error) {
         if ([weakSelf shouldRetryCall: managerCall onError: error]) {
             [self loginAndRetryCall: managerCall];
@@ -228,6 +241,23 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
         }
         [managerCall notifyFailure: error];
     };
+}
+
+- (CISDOBIpadServiceManagerCall *)managerCallWrappingServiceCall:(CISDOBAsyncCall *)serviceCall pruning:(BOOL)prune
+{
+    CISDOBIpadServiceManagerCall *managerCall = [[CISDOBIpadServiceManagerCall alloc] initWithServiceManager: self serviceCall: serviceCall];
+    
+    __weak CISDOBIpadServiceManager *weakSelf = self;
+    
+    serviceCall.success = ^(id result) {
+        weakSelf.online = YES;
+        // We treat prune as a synonym for the root set update call
+        if (prune) weakSelf.lastRootSetUpdateDate = [NSDate date];
+        // Update the cache and call the managerCall success when done
+        [weakSelf syncEntities: result pruning: prune notifying: managerCall];
+    };    
+    
+    [self initializeFailureBlockOnServiceCall: serviceCall managerCall: managerCall];
     
     return managerCall;
 }
@@ -252,18 +282,33 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
 
 - (BOOL)shouldRefreshRootLevelEntitiesCall
 {
-    if (!self.lastRootSetUpdate) return YES;
+    if (!self.lastRootSetUpdateDate) return YES;
     if (!self.service.clientPreferences) return YES;
     NSTimeInterval rootSetRefreshInterval = self.service.clientPreferences.rootSetRefreshInterval;
-    if ([[NSDate date] timeIntervalSinceDate: self.lastRootSetUpdate] < rootSetRefreshInterval) return NO;
+    if ([[NSDate date] timeIntervalSinceDate: self.lastRootSetUpdateDate] < rootSetRefreshInterval) return NO;
     return YES;
 }
 
 - (CISDOBAsyncCall *)retrieveRootLevelEntitiesFromServer
 {
-    CISDOBAsyncCall *call = [self.service listRootLevelEntities];
-        // get rid of entities not mentioned in the original call
-    CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call pruning: YES];
+    CISDOBAsyncCall *call = [self.service listNavigationalEntities];
+    
+    CISDOBIpadServiceManagerCall *managerCall = [[CISDOBIpadServiceManagerCall alloc] initWithServiceManager: self serviceCall: call];
+    
+    __weak CISDOBIpadServiceManager *weakSelf = self;
+    
+    call.success = ^(id result) {
+        weakSelf.online = YES;
+        // Update the set update date
+        weakSelf.lastRootSetUpdateDate = [NSDate date];
+        CISDOBIpadServiceManagerRetrieveRootSetCommand *command = [[CISDOBIpadServiceManagerRetrieveRootSetCommand alloc] init];
+        command.serviceManager = weakSelf;
+        command.serviceManagerCall = managerCall;
+        command.topLevelNavigationEntities = result;
+        [command run];
+    };    
+    
+    [self initializeFailureBlockOnServiceCall: call managerCall: managerCall];
     
     managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification;
     managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification;
@@ -497,11 +542,10 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
             return;
         }
     }
-    // If pruning is requested, remove entities that cannot be reached from the server result set.
-    // NOTE: This is a simplified implementation. A better solution would be to treat the intial results as a root set and trace out to do a gc, but the simpler implementation is just to remove everything that is not mentioned. We do the latter here.
-    if (_prune) {
+    // If pruning is requested, remove entities that were not updated since the prune cutoff date
+    if (_prune && self.pruneCutoffDate) {
         // Remove all entities that were not mentioned
-        NSFetchRequest *fetchRequest = [self.serviceManager fetchRequestForEntitiesNotUpdatedSince: lastUpdateDate];
+        NSFetchRequest *fetchRequest = [self.serviceManager fetchRequestForEntitiesNotUpdatedSince: self.pruneCutoffDate];
         NSArray *entitiesToDelete = [self.managedObjectContext executeFetchRequest: fetchRequest error: &error];
         for (CISDOBIpadEntity *entity in entitiesToDelete) {
             [(NSMutableArray *)_deletedEntities addObject: entity.permId];
@@ -530,6 +574,60 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
 
 @end
 
+// This class is not yet used.
+@implementation CISDOBBackgroundDataPruner
+
+// Initialization
+- (id)initWithServiceManager:(CISDOBIpadServiceManager *)serviceManager
+{
+    if (!(self = [super init])) return nil;
+    
+    _serviceManager = serviceManager;
+    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSConfinementConcurrencyType];
+    _managedObjectContext.parentContext = _serviceManager.managedObjectContext;
+    _error = nil;
+    _deletedEntities = [NSMutableArray array];
+    
+    return self;
+}
+
+// Actions
+- (void)run
+{
+    BOOL success;
+    NSError *error;
+    // If pruning is requested, remove entities that were not updated since the prune cutoff date
+    if (_prune && self.pruneCutoffDate) {
+        // Remove all entities that were not mentioned
+        NSFetchRequest *fetchRequest = [self.serviceManager fetchRequestForEntitiesNotUpdatedSince: self.pruneCutoffDate];
+        NSArray *entitiesToDelete = [self.managedObjectContext executeFetchRequest: fetchRequest error: &error];
+        for (CISDOBIpadEntity *entity in entitiesToDelete) {
+            [(NSMutableArray *)_deletedEntities addObject: entity.permId];
+            [self.managedObjectContext deleteObject: entity];
+        }
+    }
+    
+    success = [self.managedObjectContext save: &error];
+    if (!success) {
+        self.error = error;
+        return;
+    }
+    
+    self.error = nil;
+}
+
+- (void)notifyCallOfResult
+{
+    if (self.error) {
+        [self.managerCall notifyFailure: self.error];
+    } else if (self.managerCall.success) {
+        [self.managerCall notifySuccess: nil];
+    }
+    
+}
+
+@end
+
 @implementation CISDOBIpadImage
 
 
@@ -648,5 +746,54 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
     _connection = nil;
 }
 
+@end
+
+@implementation CISDOBIpadServiceManagerRetrieveRootSetCommand
+
+- (void)runNextCall
+{
+    NSUInteger currentIndex = self.currentIndex, count = [self.topLevelNavigationEntities count];
+    CISDOBIpadEntity *navEntity = [self.topLevelNavigationEntities objectAtIndex:  currentIndex];
+
+    NSArray *permIds = [NSArray arrayWithObject: navEntity.permId];
+    NSArray *refcons = [NSArray arrayWithObject: navEntity.refcon];
+    CISDOBAsyncCall *call = [self.serviceManager.service listRootLevelEntities: permIds refcons: refcons];
+    call.success = ^(id result) {
+        if (currentIndex+1 == count) {
+            [self.serviceManager syncEntities: result pruning: YES notifying: self.serviceManagerCall];
+        } else {
+            [self.serviceManager syncEntities: result pruning: NO notifying: nil];
+            [self runNextCall];
+        }
+    };    
+    [self.serviceManager initializeFailureBlockOnServiceCall: call managerCall: self.serviceManagerCall];
+    self.currentIndex = currentIndex + 1;
+    [call start];
+}
+
+- (void)run
+{
+    self.currentIndex = 0;
+    if ([self.topLevelNavigationEntities count] < 1) {
+        // Did not retrieve the topLevelNavigationEntities. Just call
+        // listRootLevelEntites without arguments
+        NSArray *permIds = [NSArray array];
+        NSArray *refcons = [NSArray array];
+        CISDOBAsyncCall *call = [self.serviceManager.service listRootLevelEntities: permIds refcons: refcons];
+    
+        call.success = ^(id result) {
+           [self.serviceManager syncEntities: result pruning: YES notifying: self.serviceManagerCall];
+        };
+        [self.serviceManager initializeFailureBlockOnServiceCall: call managerCall: self.serviceManagerCall];
+        [call start];
+        return;
+    }
+    
+    // First add the navigation entities
+    [self.serviceManager syncEntities: self.topLevelNavigationEntities pruning: NO notifying: nil];
+    
+    // Go through each of the navigation entities and get the roots for them
+    [self runNextCall];
+}
 
 @end
diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManagerInternal.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManagerInternal.h
index aadd69243114a7b059f7b8eeb36239f8a4c5cdc5..a09651015330d84e21ba29ea99f7c020e8aeebc8 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManagerInternal.h
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManagerInternal.h
@@ -58,6 +58,22 @@
 
 @end
 
+// An object that carries out all the steps that need to run after the user has logged into the server
+@interface CISDOBIpadServiceManagerRetrieveRootSetCommand : NSObject
+
+// These properties must all be set before running the commmand
+@property(weak, nonatomic) CISDOBIpadServiceManager *serviceManager;
+@property(weak, nonatomic) CISDOBIpadServiceManagerCall *serviceManagerCall;
+@property(strong, nonatomic) NSArray *topLevelNavigationEntities;
+
+// This property is updated while running
+@property(nonatomic) NSUInteger currentIndex;
+
+// Actions
+- (void)run;
+
+@end
+
 // Internal methods of the service manager
 @interface CISDOBIpadServiceManager (CISDOBIpadServiceManagerInternal)
 - (BOOL)shouldRefreshRootLevelEntitiesCall;
diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadEntityTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadEntityTest.m
index 7d1945d61ba42797ca47463bd13294fc57b7a61d..7631806b412c3ec3665cbe4a52837f365d960ba6 100644
--- a/openbis-ipad/BisKit/Tests/CISDOBIpadEntityTest.m
+++ b/openbis-ipad/BisKit/Tests/CISDOBIpadEntityTest.m
@@ -193,13 +193,21 @@ NSManagedObjectContext* GetDatabaseManagedObjectContext(NSURL* storeURL, NSError
     }
 }
 
+- (CISDOBIpadRawEntity *)entityForRootCall:(NSArray *)navigationalEntities
+{
+    return [navigationalEntities objectAtIndex: 1];
+}
+
 - (void)testPersistEntities
 {
     CISDOBAsyncCall *call;
     call = [_service loginUser: GetDefaultUserName() password: GetDefaultUserPassword()];
     [self configureAndRunCallSynchronously: call];
     
-    call = [_service listRootLevelEntities];
+    call = [_service listNavigationalEntities];
+    [self configureAndRunCallSynchronously: call];
+    CISDOBIpadRawEntity *entityForRoot = [self entityForRootCall: _callResult];
+    call = [_service listRootLevelEntities: [NSArray arrayWithObject: entityForRoot.permId] refcons: [NSArray arrayWithObject: entityForRoot.refcon]];
     [self configureAndRunCallSynchronously: call];
     
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
index 838b954830cc719ebc4d2c07c3ac44464647070e..b6ad115872ec4ff0740a028b566577bbcfdf5af3 100644
--- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
+++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
@@ -31,6 +31,16 @@
 #import "CISDOBConnectionInternal.h"
 #import "CISDOBIpadEntity.h"
 
+static BOOL IsPermIdCompound(NSString *permId)
+{
+    return [permId hasSuffix: @"5HT_COMPOUND)"];
+}
+
+static BOOL IsPermIdTarget(NSString *permId)
+{
+    return [permId hasSuffix: @"5HT_TARGET)"];
+}
+
 @implementation CISDOBIpadServiceManagerTest
 
 - (void)processNotification:(NSNotification *)note
@@ -132,6 +142,23 @@
     [self waitSeconds: waitTime forCallToComplete: call];
 }
 
+- (NSArray *)targetsAndCompounds
+{
+	NSError *error;
+	NSFetchRequest* request = [self.serviceManager fetchRequestForEntities];
+    
+   	NSArray *elements = [self.serviceManager executeFetchRequest: request error: &error];
+    
+    NSMutableArray *targetsAndCompounds = [NSMutableArray array];
+    for (CISDOBIpadEntity *entity in elements) {
+        if (IsPermIdCompound(entity.permId) || IsPermIdTarget(entity.permId)) {
+            [targetsAndCompounds addObject: entity];
+        }
+    }
+    
+    return targetsAndCompounds;
+}
+
 - (NSArray *)entitiesWithChildren
 {
 	NSError *error;
@@ -141,7 +168,7 @@
     
     NSMutableArray *entitiesWithChildren = [NSMutableArray array];
     for (CISDOBIpadEntity *entity in elements) {
-        if ([entity.childrenPermIds count] > 0) {
+        if ([entity.childrenPermIds count] > 0 && ![@"Navigation" isEqualToString: entity.category]) {
             [entitiesWithChildren addObject: entity];
         }
     }
@@ -149,6 +176,23 @@
     return entitiesWithChildren;
 }
 
+- (NSArray *)navigationEntities
+{
+	NSError *error;
+	NSFetchRequest* request = [self.serviceManager fetchRequestForEntities];
+    
+   	NSArray *elements = [self.serviceManager executeFetchRequest: request error: &error];
+    
+    NSMutableArray *navigationEntities = [NSMutableArray array];
+    for (CISDOBIpadEntity *entity in elements) {
+        if ([@"Navigation" isEqualToString: entity.category]) {
+            [navigationEntities addObject: entity];
+        }
+    }
+    
+    return navigationEntities;
+}
+
 - (void)checkFindingChildren
 {
 	NSError* error;
@@ -334,13 +378,13 @@
     NSLog(@"Error %@", _callError);
 }
 
-- (void)retrieveRootLevelEntitiesSimulatingRemovalOfEntity:(CISDOBIpadEntity *)entityToRemove
+- (void)retrieveRootLevelEntitiesSimulatingRemovalOfCategory:(CISDOBIpadEntity *)categoryToRemove
 {
     // Make a root level call, but do have some entities removed from the list
     CISDOBAsyncCall *call;
     call = [self.serviceManager retrieveRootLevelEntitiesFromServer];
     
-    NSArray *removedEntities = [self.serviceManager.service convertToEntitiesPermIds: [NSArray arrayWithObject: entityToRemove.permId] refcons: [NSArray arrayWithObject: entityToRemove.refcon] count: 1];
+    NSArray *removedEntities = [self.serviceManager.service convertToEntitiesPermIds: [NSArray arrayWithObject: categoryToRemove.permId] refcons: [NSArray arrayWithObject: categoryToRemove.refcon] count: 1];
     CISDOBIpadServiceCall *serviceCall = (CISDOBIpadServiceCall *)((CISDOBIpadServiceManagerCall *)call).serviceCall;
     CISDOBConnectionCall *connectionCall = (CISDOBConnectionCall *) serviceCall.connectionCall;
     NSArray *oldParams = connectionCall.params;
@@ -362,18 +406,42 @@
     [self performLogin];
     [self performRootLevelCall];
     
+    // Figure out how many targets and compounds are available
+    NSUInteger targetsAndCompoundsCount = [[self targetsAndCompounds] count];
+    
     // Pick an entity to remove from the next result set to simulate deletion
-    NSArray *entitiesWithChildren = [self entitiesWithChildren];
-    CISDOBIpadEntity *entityToRemove = [entitiesWithChildren objectAtIndex: 0];
+    NSArray *navigationEntities = [self navigationEntities];
+    CISDOBIpadEntity *categoryToRemove;
+    for (CISDOBIpadEntity *entity in navigationEntities) {
+        if ([@"TARGETS AND COMPOUNDS" isEqualToString: entity.permId]) {
+            categoryToRemove = entity;
+            break;
+        }
+    }
     // Remember the permId before we refresh because the entity will be deleted
-    NSArray *removedPermIds = [NSArray arrayWithObject: entityToRemove.permId];
-    
+    NSMutableArray *removedPermIds = [NSMutableArray array];
     self.serviceManager.mocSaveBlock = ^(CISDOBIpadServiceManager *manager, NSArray *entitiesToDelete) {
-        STAssertEquals((NSUInteger) 1, [entitiesToDelete count], @"Only one entity should be deleted");
-        STAssertEqualObjects(entityToRemove.permId, [entitiesToDelete objectAtIndex: 0],  @"Only the specified object should be deleted");
+        // This block is invoked on each save. Not all saves will delete entities
+        if ([entitiesToDelete count] < 1) return;
+        
+        [removedPermIds addObjectsFromArray: entitiesToDelete];
+        STAssertEquals((NSUInteger) targetsAndCompoundsCount + 1, [entitiesToDelete count], @"All targets and compounds should be deleted.");
+        NSUInteger navCount = 0, compoundCount = 0, targetCount = 0;
+        for (NSString *entityPermId in entitiesToDelete) {
+            BOOL is5HTCompound = IsPermIdCompound(entityPermId);
+            BOOL is5HTTarget = IsPermIdTarget(entityPermId);
+            BOOL isNav = [@"TARGETS AND COMPOUNDS" isEqualToString: entityPermId];
+            STAssertTrue(is5HTCompound || is5HTTarget || isNav, @"The deleted entities should be either targets or compounds");
+            if (is5HTCompound) ++compoundCount;
+            if (is5HTTarget) ++targetCount;
+            if (isNav) ++navCount;
+        }
+        STAssertEquals((NSUInteger) 1, navCount, @"Only one navigational entity should have been deleted");
+        STAssertEquals((NSUInteger) 204, compoundCount, @"204 compound entities should have been deleted");
+        STAssertEquals((NSUInteger) 29, targetCount, @"29 target entities should have been deleted");
     };
 
-    [self retrieveRootLevelEntitiesSimulatingRemovalOfEntity: entityToRemove];
+    [self retrieveRootLevelEntitiesSimulatingRemovalOfCategory: categoryToRemove];
     
     // Check that the entityToRemove is no longer found
     NSError *error;
@@ -381,7 +449,7 @@
     STAssertEquals([removedEntities count], (NSUInteger) 0, @"Removed entities should not be found anymore");
 
     // Check that entityToRemove is still accessible
-    STAssertNil(entityToRemove.permId, @"The Entity's fields should have been set to nil");
+    STAssertNil(categoryToRemove.permId, @"The Entity's fields should have been set to nil");
 }
 
 - (void)testImageRetrieval
diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceTest.m
index 73de90f7d68efcd3d90bee84785f2eee0e7d15e5..6563796f91576024f870de6234bf72515386315b 100644
--- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceTest.m
+++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceTest.m
@@ -55,6 +55,11 @@
     [self waitSeconds: waitTime forCallToComplete: call];
 }
 
+- (CISDOBIpadRawEntity *)entityForRootCall:(NSArray *)navigationalEntities
+{
+    return [navigationalEntities objectAtIndex: 1];
+}
+
 - (void)testListNavigationalEntities
 {
     CISDOBAsyncCall *call;
@@ -87,8 +92,11 @@
     [self configureAndRunCallSynchronously: call];
     STAssertNotNil(_service.clientPreferences, @"The client preferences should have been initialized");
     STAssertEquals(_service.clientPreferences.rootSetRefreshInterval, 60. * 30., @"The default root refresh interval should be 30 min");
-    
-    call = [_service listRootLevelEntities];
+
+    call = [_service listNavigationalEntities];
+    [self configureAndRunCallSynchronously: call];
+    CISDOBIpadRawEntity *entityForRoot = [self entityForRootCall: _callResult];
+    call = [_service listRootLevelEntities: [NSArray arrayWithObject: entityForRoot.permId] refcons: [NSArray arrayWithObject: entityForRoot.refcon]];
     [self configureAndRunCallSynchronously: call];
     
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
@@ -117,7 +125,10 @@
     call = [_service loginUser: GetDefaultUserName() password: GetDefaultUserPassword()];
     [self configureAndRunCallSynchronously: call];
     
-    call = [_service listRootLevelEntities];
+    call = [_service listNavigationalEntities];
+    [self configureAndRunCallSynchronously: call];
+    CISDOBIpadRawEntity *entityForRoot = [self entityForRootCall: _callResult];
+    call = [_service listRootLevelEntities: [NSArray arrayWithObject: entityForRoot.permId] refcons: [NSArray arrayWithObject: entityForRoot.refcon]];
     [self configureAndRunCallSynchronously: call];
     
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
@@ -160,7 +171,10 @@
     call = [_service loginUser: GetDefaultUserName() password: GetDefaultUserPassword()];
     [self configureAndRunCallSynchronously: call];
     
-    call = [_service listRootLevelEntities];
+    call = [_service listNavigationalEntities];
+    [self configureAndRunCallSynchronously: call];
+    CISDOBIpadRawEntity *entityForRoot = [self entityForRootCall: _callResult];
+    call = [_service listRootLevelEntities: [NSArray arrayWithObject: entityForRoot.permId] refcons: [NSArray arrayWithObject: entityForRoot.refcon]];
     [self configureAndRunCallSynchronously: call];
     
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
diff --git a/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate
index 08b77991592b08444d9cccedf10cb4fc4a5b3430..b73fb10ef280df291004fd652e5aab016f7781f8 100644
Binary files a/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/Test Minimal.xcscheme b/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/Test Minimal.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..e3c0e9998ccb7cb824e3712655aa90ecb39d5be3
--- /dev/null
+++ b/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/Test Minimal.xcscheme	
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0450"
+   version = "1.8">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "3680779F15D0F78700843AD5"
+               BuildableName = "BisMac.app"
+               BlueprintName = "BisMac"
+               ReferencedContainer = "container:BisMac.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "368077C615D0F78700843AD5"
+               BuildableName = "BisMacTests.octest"
+               BlueprintName = "BisMacTests"
+               ReferencedContainer = "container:BisMac.xcodeproj">
+            </BuildableReference>
+            <SkippedTests>
+               <Test
+                  Identifier = "BisMacTests">
+               </Test>
+               <Test
+                  Identifier = "CISDOBAsyncTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBIpadEntityTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBJsonRpcCallGenericTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBJsonRpcCallOpenBisTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBJsonRpcCallTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBLiveConnectionTest">
+               </Test>
+               <Test
+                  Identifier = "CISDOBIpadServiceTest">
+               </Test>
+            </SkippedTests>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      displayScaleIsEnabled = "NO"
+      displayScale = "1.00"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3680779F15D0F78700843AD5"
+            BuildableName = "BisMac.app"
+            BlueprintName = "BisMac"
+            ReferencedContainer = "container:BisMac.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      displayScaleIsEnabled = "NO"
+      displayScale = "1.00"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3680779F15D0F78700843AD5"
+            BuildableName = "BisMac.app"
+            BlueprintName = "BisMac"
+            ReferencedContainer = "container:BisMac.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/xcschememanagement.plist b/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/xcschememanagement.plist
index 6fda79585ec87887fd52db30ba83577ffca64266..e287e2d51cc3ac398a02553f5150263994fba539 100644
--- a/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/openbis-ipad/Research/BisMac.xcodeproj/xcuserdata/cramakri.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -19,6 +19,11 @@
 			<key>orderHint</key>
 			<integer>3</integer>
 		</dict>
+		<key>Test Minimal.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>1</integer>
+		</dict>
 		<key>YeastLab.xcscheme</key>
 		<dict>
 			<key>orderHint</key>
diff --git a/openbis-ipad/core-plugin/readme.md b/openbis-ipad/core-plugin/readme.md
index b48d6ce448676c250ea5ca4534a0800307e89ca1..d0d040a51cfd41d33d8c96dace0dfadd54da21ed 100644
--- a/openbis-ipad/core-plugin/readme.md
+++ b/openbis-ipad/core-plugin/readme.md
@@ -193,8 +193,8 @@ The communication model between the iPad and the service has been designed to tr
 		</tr>		
 		<tr>
 			<td>ROOT</td>
-			<td>None</td>
-			<td>Return root entities.</td>
+			<td>entities : List of {"PERM_ID" : String, REFCON : String}</td>
+			<td>Return root entities for the specified navigational entities</td>
 			<td>Used to track which entities should be constantly available on the iPad.</td>
 			<td>PERM_ID, REFCON, CATEGORY, SUMMARY_HEADER, SUMMARY, CHILDREN, ROOT_LEVEL</td>
 		</tr>
diff --git a/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/index.html b/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/index.html
index d3c362ce26703358c7fb2c40cc033f32c75d6be0..91617b2c543a8af8fa1a7e9892b0f0920357f293 100644
--- a/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/index.html
+++ b/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/index.html
@@ -67,8 +67,17 @@
 	    </div>
 	
 	    <div class="container">
-	
-	      <h1>Root</h1>
+
+        <h1>Client Preferences</h1>
+        <div class="row-fluid">
+            <div id="clientprefs" class="span12" style="overflow: auto;"></div>
+        </div>
+
+        <h1>Navigation</h1>
+        <div class="row-fluid">
+            <div id="navigation" class="span12" style="overflow: auto;"></div>
+        </div>
+	    <h1>Root</h1>
         <div class="row-fluid">
             <div id="root" class="span12" style="height: 410px; overflow: auto;"></div>
         </div>
diff --git a/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/webapp.js b/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/webapp.js
index feaf9f4f96cd4a929eddf109c681146417415a17..cd74fb9aeab31e2dd2f8477693fddf5a6af2b116 100644
--- a/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/webapp.js
+++ b/openbis-ipad/ipad-example-data/ipad-ui/1/as/webapps/ipad-debug/html/webapp.js
@@ -30,13 +30,26 @@ IpadModel.prototype.selectEntity = function(d) {
 	this.selectedEntity = d;
 	var permId = d[0].value;
 	var refcon = parseJson(d[1].value);
+	var rootLevel = d[5].value;
+	if ("True" == rootLevel) {
+		this.selectNavigationEntity(permId, refcon);
+	} else {
+		this.selectNormalEntity(permId, refcon, d);
+	}
+}
+
+IpadModel.prototype.selectNavigationEntity = function(permId, refcon) {
+	listRootLevelEntities(permId, refcon);
+}
+
+IpadModel.prototype.selectNormalEntity = function(permId, refcon, d) {
 	var children = parseJson(d[5].value);
 	if (children.length > 0) {
 		drillOnEntity(permId, refcon);
 		detailsForEntity(permId, refcon);
 	} else {
 		detailsForEntity(permId, refcon);
-	}
+	}	
 }
 
 /// The model that manages state and implements the operations
@@ -45,7 +58,7 @@ model = new IpadModel();
 
 
 /// The visualization, referenced by functions that display content
-var root, drill, detail;
+var clientPrefs, navigation, root, drill, detail;
 
 /**
  * Create the DOM elements to store the visualization (tree + inspectors)
@@ -55,6 +68,8 @@ function createVis()
 	if (didCreateVis) return;
 	
 	// Create a div to house the tree visualization and the inspectors
+	clientPrefs = d3.select("#clientprefs");
+	navigation = d3.select("#navigation");
 	root = d3.select("#root");
 	drill = d3.select("#drill");	
 	detail = d3.select("#detail");
@@ -116,6 +131,17 @@ function displayResults(node, data)
 	showTableData(table);
 }
 
+function displayClientPreferences(data)
+{
+	displayResults(clientPrefs, data)
+}
+
+
+function displayNavigation(data)
+{
+	displayResults(navigation, data)
+}
+
 function displayRoot(data)
 {
 	displayResults(root, data)
@@ -123,7 +149,6 @@ function displayRoot(data)
 
 function displayDrill(data)
 {
-	console.log(data);
 	displayResults(drill, data)
 }
 
@@ -133,11 +158,32 @@ function displayDetail(data)
 }
 
 /**
- * Request samples matching some criteria from the server and show them in the Page.
+ * Request the client perferences and show them in the page.
  */
-function listRootLevelEntities()
+function listClientPreferences()
 {
-	var parameters = {requestKey : 'ROOT'};
+	var parameters = {requestKey : 'CLIENT_PREFS'};
+
+	openbisServer.createReportFromAggregationService("DSS1", "ipad-read-service-v1", parameters, displayClientPreferences);
+}
+
+/**
+ * Request the top-level navigational entities and show them in the page
+ */
+function listNavigationEntities()
+{
+	var parameters = {requestKey : 'NAVIGATION'};
+
+	openbisServer.createReportFromAggregationService("DSS1", "ipad-read-service-v1", parameters, displayNavigation);
+}
+
+/**
+ * Request samples matching some criteria from the server and show them in the page.
+ */
+function listRootLevelEntities(permId, refcon)
+{
+	var entities = [{"PERM_ID" : permId, "REFCON" : refcon}];
+	var parameters = {requestKey : 'ROOT', entities: entities};
 
 	openbisServer.createReportFromAggregationService("DSS1", "ipad-read-service-v1", parameters, displayRoot);
 }
@@ -171,5 +217,6 @@ function enterApp(data)
     $('#main').show();
 
     createVis();
-    listRootLevelEntities();
+    listClientPreferences();
+    listNavigationEntities();
 }
\ No newline at end of file
diff --git a/openbis-ipad/ipad-example-data/ipad-ui/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py b/openbis-ipad/ipad-example-data/ipad-ui/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
index f84d9af463b4dae8a8242bf89d68f59f39c41719..ee7a9fbb4ff037a69e4d78ab705969719841730e 100644
--- a/openbis-ipad/ipad-example-data/ipad-ui/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
+++ b/openbis-ipad/ipad-example-data/ipad-ui/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
@@ -11,7 +11,7 @@ def json_encoded_value(coll):
 	"""Utility function for converting a list into a json-encoded list"""
 	return ObjectMapper().writeValueAsString(coll)
 
-class RequestHandler:
+class RequestHandler(object):
 	"""Abstract superclass for the handlers for concrete requests like ROOT.
 
 	This superclass defines behavior common to all requests.
@@ -34,6 +34,13 @@ class RequestHandler:
 		global searchService
 		self.searchService = searchService
 		self.headers = ['PERM_ID', 'REFCON'] + self.optional_headers()
+		
+	def entities_parameter(self):
+	  """A helper method to get the value of the entities parameter. Returns an empty list if no entities were specified"""
+	  entities = self.parameters.get('entities')
+	  if entities is None:
+	    return []
+	  return entities
 
 
 	def optional_headers(self):
@@ -97,7 +104,7 @@ class RequestHandler:
 		self.retrieve_data()
 		self.add_data_rows()
 
-class ClientPreferencesRequestHandler:
+class ClientPreferencesRequestHandler(object):
 	"""Abstract superclass for the handlers for CLIENT_PREFS request.
 
 	This request has a slightly different structure, since it does not return entities.
@@ -398,7 +405,19 @@ class ExampleClientPreferencesRequestHandler(ClientPreferencesRequestHandler):
 class ExampleRootRequestHandler(RootRequestHandler):
 	"""Handler for the ROOT request."""
 
+	def entities_parameter(self):
+		entities = super(ExampleRootRequestHandler, self).entities_parameter()
+		if len(entities) == 0:
+			materials_nav = navigation_dict('Targets and Compounds', [])
+			probe_nav = navigation_dict('Probes', [])
+			return [materials_nav, probe_nav]
+		return entities
+
 	def retrieve_data(self):
+		# Check which navigational entities are being requested here
+		nav_entities = self.entities_parameter()
+		nav_perm_ids = [entity['PERM_ID'] for entity in nav_entities]
+
 		# Get the data and add a row for each data item
 		self.samples = self.searchService.searchForSamples("DESC", "*", "5HT_PROBE")
 		material_identifiers = gather_materials(self.samples)
@@ -406,27 +425,28 @@ class ExampleRootRequestHandler(RootRequestHandler):
 		self.material_dict_array = materials_to_dict(materials, {})
 		self.material_by_perm_id = dict([(material.getMaterialIdentifier(), material) for material in materials])
 
-	def add_navigation_rows(self):
-		"""Add entities that are purely for navigation"""
-		children = [material_dict['PERM_ID'] for material_dict in self.material_dict_array]
-		materials_nav = navigation_dict('Targets and Compounds', children)
+	def add_data_rows(self):
+		nav_entities = self.entities_parameter()
+		nav_perm_ids = [entity['PERM_ID'] for entity in nav_entities]
 
-		children = [sample.getPermId() for sample in self.samples]
-		probe_nav = navigation_dict('Probes', children)
-		self.add_rows([materials_nav, probe_nav])
+		if 'TARGETS AND COMPOUNDS' in nav_perm_ids:
+			children = [material_dict['PERM_ID'] for material_dict in self.material_dict_array]
+			materials_nav = navigation_dict('Targets and Compounds', children)
+			self.add_rows([materials_nav])
+			self.add_rows(self.material_dict_array)
 
-
-	def add_data_rows(self):
-		self.add_navigation_rows()
-		self.add_rows(self.material_dict_array)
-		self.add_rows(samples_to_dict(self.samples, self.material_by_perm_id, {}))
+		if 'PROBES' in nav_perm_ids:
+			children = [sample.getPermId() for sample in self.samples]
+			probe_nav = navigation_dict('Probes', children)
+			self.add_rows([probe_nav])
+			self.add_rows(samples_to_dict(self.samples, self.material_by_perm_id, {}))
 
 class ExampleDrillRequestHandler(DrillRequestHandler):
 	"""Handler for the DRILL request."""
 
 	def retrieve_data(self):
 		# Drill only happens on samples
-		drill_samples = self.parameters['entities']
+		drill_samples = self.entities_parameter()
 
 		self.samples = retrieve_samples(drill_samples)
 		material_identifiers = gather_materials(self.samples)
@@ -443,7 +463,7 @@ class ExampleDetailRequestHandler(DetailRequestHandler):
 
 	def retrieve_data(self):
 		# Get the data and add a row for each data item
-		entities = self.parameters['entities']
+		entities = self.entities_parameter()
 		detail_samples = [entity for entity in entities if 'SAMPLE' == entity['REFCON']['entityKind']]
 		detail_materials = [entity for entity in entities if 'MATERIAL' == entity['REFCON']['entityKind']]
 
@@ -475,38 +495,30 @@ class ExampleNavigationRequestHandler(NavigationRequestHandler):
 		probe_nav = navigation_dict('Probes', [])
 		self.add_rows([materials_nav, probe_nav])
 
-class TestingRootRequestHandler(ExampleRootRequestHandler):
-	"""A version of the root request handler designed for testing"""
-
-	def hide_hidden_samples(self):
-		"""A method used in testing to simulate the removal of a sample from the database.
-
-		Production code does not need to implement or use this method"""
+class TestingNavigationRequestHandler(ExampleNavigationRequestHandler):
+	"""A version of the NAVIGATION request handler designed for testing"""
 
+	def add_data_rows(self):
 		hidden_entities = self.parameters.get("HIDE")
 		if hidden_entities is None:
-			return
+			hidden_entities = []
 		hidden_perm_ids = set([entity["PERM_ID"] for entity in hidden_entities])
 
-		count = len(self.samples)
-		for indexPlus1 in range(count, 0, -1):
-			index = indexPlus1 - 1
-			if self.samples[index].getPermId() in hidden_perm_ids:
-				del self.samples[index]
-
-	def retrieve_data(self):
-		ExampleRootRequestHandler.retrieve_data(self)
-		# Used to simulate samples being removed from the database. Not designed for production code
-		self.hide_hidden_samples()
+		if 'TARGETS AND COMPOUNDS' not in hidden_perm_ids:
+			materials_nav = navigation_dict('Targets and Compounds', [])
+			self.add_rows([materials_nav])
+		if 'PROBES' not in hidden_perm_ids:
+			probe_nav = navigation_dict('Probes', [])
+			self.add_rows([probe_nav])
 
 def aggregate(parameters, builder):
 	request_key = parameters.get('requestKey')
 	if 'CLIENT_PREFS' == request_key:
 		handler = ExampleClientPreferencesRequestHandler(parameters, builder)
 	elif 'NAVIGATION' == request_key:
-		handler = ExampleNavigationRequestHandler(parameters, builder)
+		handler = TestingNavigationRequestHandler(parameters, builder)
 	elif 'ROOT' == request_key:
-		handler = TestingRootRequestHandler(parameters, builder)
+		handler = ExampleRootRequestHandler(parameters, builder)
 	elif 'DRILL' == request_key:
 		handler = ExampleDrillRequestHandler(parameters, builder)
 	elif 'DETAIL' == request_key:
diff --git a/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate
index b1103cc0e75a3549078f5c4d9b6a5d8d79961c03..9fad6cf1acb50ec12347fc73b05c6974e12bdab8 100644
Binary files a/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ