public void Navigate()
{
    // Browse the vault from the root.
    string userChoice = "";
    string currentPath = "";
    while( userChoice != null )
    {
        // Construct the path.
        // This will result in '/v1/v2/' format.
        // Root path will be represented with just '/'.
        currentPath += userChoice + "/";
        userChoice = PromptView( currentPath );
    }
}

public string PromptView(string path)
{
    // Get view contents.
    var contents = GetViewContents( path );

    // Display objects
    var objects = contents.Items
        .Select( i => i.ObjectVersion )
        .Where( i => i != null ).ToList();

    // List objects
    Console.WriteLine( "Objects in this view:" );
    foreach( ObjectVersion o in objects )
        Console.WriteLine( o.Title );
    Console.WriteLine();

    // We'll gather all possible navigation targets in one list.
    List<object> navigableItems = new List<object>();

    // List views
    var views = contents.Items
        .Select( i => i.View )
        .Where( i => i != null ).ToList();

    Console.WriteLine( "Other views in this view:" );
    foreach( View v in views )
    {
        // Add the view to the list as a possible navigation target.
        // Also prefix the view name with its index in the list.
        navigableItems.Add( v );
        Console.WriteLine( "{0}: {1}", navigableItems.Count, v.Name );
    }
    Console.WriteLine();

    // Display property folders.
    var propertyFolders = contents.Items
        .Select( i => i.PropertyFolder )
        .Where( i => i != null ).ToList();

    Console.WriteLine( "Property folders in this view:" );
    foreach( TypedValue p in propertyFolders )
    {
        // Add the property folder to the list as a possible navigation target.
        // Also prefix the view name with its index in the list.
        navigableItems.Add( p );
        Console.WriteLine( "{0}: {1}", navigableItems.Count, p.DisplayValue );
    }
    Console.WriteLine();

    // Read the user input for the next view.
    object nextItem;
    while( true )
    {
        Console.WriteLine( "Select the next directory or type 'q' to exit:" );
        string input = Console.ReadLine();

        // 'q' stop the navigation.
        if( input == "q" ) return null;

        // Parse the string input.
        int index;
        if( !int.TryParse( input, out index ) )
        {
            Console.WriteLine( "Invalid input!" );
            Console.WriteLine();
            continue;
        }

        // Make sure the string is within the valid range.
        if( index < 1 || index > navigableItems.Count )
        {
            Console.WriteLine( "Input out of range!" );
            Console.WriteLine();
            continue;
        }

        // Input was okay so we can select the next item.
        nextItem = navigableItems[ index - 1 ];
        break;
    }

    // Depending on the item type, construct the view path differently.

    // For views we need to prefix the ID with a 'v'.
    if( nextItem is View ) return "v" + ( ( View )nextItem ).ID;

    // For property folders we need to decide on the prefix based on datatype
    // and after this we can use the SerializedValue from the TypedValue.
    if( nextItem is TypedValue )
    {
        string prefix;
        TypedValue tv = ((TypedValue) nextItem);
        switch( tv.DataType )
        {
            case MFDataType.Lookup:
                prefix = "l";
                break;
            case MFDataType.MultiLineText:
                prefix = "s";
                break;
            case MFDataType.Text:
                prefix = "t";
                break;
            default:
                throw new NotImplementedException();
        }
        return prefix + tv.SerializedValue;
    }

    return null;
}

public FolderContentItems GetViewContents( string path )
{
    // Construct the URL by filling path.
    // Note that the input path in our case is in "/foo/bar/" format.
    string url = "http://example.org/REST/views" + path + "items";

    // Create the web request.
    WebRequest request = WebRequest.Create( url );

    // Fill the authentication information.
    request.Headers["X-Authentication"] = this.AuthenticationToken;

    // Get the response.
    var response = request.GetResponse();

    // Use JSON serializer to deserialize the FolderContentItems from the response.
    var serializer = new DataContractJsonSerializer( typeof( FolderContentItems ) );
    var items = (FolderContentItems)serializer.ReadObject( response.GetResponseStream() );

    return items;
}