# Console application to manage Onelake storage in Microsoft Fabric

My previous [article](https://www.azureguru.net/adls-gen2-api-to-manage-onelake-storage-in-microsoft-fabric) demonstrated the use of Azure Storage API to manage Onelake in Fabric. This made me thinking if its possible to create a custom application that can leverage those API's outside the Fabric environment.

So I ended up created this small .NET console application in C#. Nothing fancy just simple console based interface that can perform basic storage level operations over the lakehouses.

Here is the walkthrough of the application functionality.

%[https://www.youtube.com/watch?v=9lw3H1fe2FI] 

<s>The code I developed to create the application is in a mess. I need to modularize it. Once done I will upload it to Github and also share it here.</s>

**Update 1/19/2024 :** I completed cleaning up the code and modularize it.

The updated code is uploaded [here](https://github.com/Sachin-Nand/Console-application-to-manage-Onelake-storage-in-Microsoft-Fabric.git) on GitHub.

**Updates** : Created three additional classes

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1737306821690/07f5a523-45cf-43b9-9864-eefe7f82c614.png align="left")

`Program.cs` being the entry point into the application.

`Authentication.cs` returns the bearer token

`Actions.cs` performing various storage level actions

`HttpMethods.cs` containing the various Http methods

`HttpMethods` class inherits `Authentication` class and the `Program` class inherits the `Actions` class.

@ minute 6:20 in the above video [https://youtu.be/9lw3H1fe2FI&t=380](https://youtu.be/9lw3H1fe2FI&t=380) I mentioned that its not possible to provide a confirmation dialog in a console based app. I made some changes and instead added a prompt based confirmation.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1737312730146/8e709876-4d22-4ec3-b1c8-bcc4b91a50a4.png align="left")

### **Code**

In the application ensure that you have the following `Nuget` packages installed.

```csharp
dotnet add package Spectre.Console --version 0.49.1
dotnet add package Newtonsoft.Json --version 13.0.3
dotnet add package Microsoft.Extensions.Configuration.Json --version 9.0.1
dotnet add package Microsoft.Extensions.Configuration --version 9.0.1
dotnet add package Microsoft.Identity.Client --version 4.67.2
dotnet add package Spectre.Console --version 0.49.2-preview.0.69
dotnet add package Azure.Storage.Files.DataLake --version 12.21.0
```

### Appsettings.json

```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ClientId": "Service Principal Client Id",
  "DownloadLocation": "Download location to download files from the Fabirc tenant"
}
```

### Authentication.cs

```csharp
using Microsoft.Identity.Client;

namespace Security
{
    internal class Authentication
    {
        public static bool istokencached = false;
        public static string clientId = "";
        private static string[] scopes = new string[] { "https://storage.azure.com/.default" };
        private static string Authority = "https://login.microsoftonline.com/organizations";
        private static string RedirectURI = "http://localhost";
        public static readonly HttpClient client = new HttpClient();
        protected HttpClient Client => client;
        public async static Task<AuthenticationResult> ReturnAuthenticationResult()
        {
            string AccessToken;
            PublicClientApplicationBuilder PublicClientAppBuilder =
                PublicClientApplicationBuilder.Create(clientId)
                .WithAuthority(Authority)
                .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
                .WithRedirectUri(RedirectURI);

            IPublicClientApplication PublicClientApplication = PublicClientAppBuilder.Build();
            var accounts = await PublicClientApplication.GetAccountsAsync();
            AuthenticationResult result;
            try
            {

                result = await PublicClientApplication.AcquireTokenSilent(scopes, accounts.First())
                                 .ExecuteAsync()
                                 .ConfigureAwait(false);

            }
            catch
            {
                result = await PublicClientApplication.AcquireTokenInteractive(scopes)
                                 .ExecuteAsync()
                                 .ConfigureAwait(false);

            }
            istokencached = true;
            return result;

        }
    }
}
```

### HttpsMethods.cs

```csharp
using System.Net.Http.Headers;
using Microsoft.Identity.Client;

namespace Http
{
    internal class HttpMethods : Security.Authentication
    {
        public async static Task<string> GetAsync(string url)
        {

            AuthenticationResult result = await ReturnAuthenticationResult();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.GetAsync(url);
            try
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                return null;
            }

        }

        public async static Task<byte[]> SendAsync(HttpRequestMessage httprequestMessage)
        {
            AuthenticationResult result = await ReturnAuthenticationResult();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.SendAsync(httprequestMessage);
            response.EnsureSuccessStatusCode();
            try
            {
                return await response.Content.ReadAsByteArrayAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsByteArrayAsync().Result);
                return null;
            }
        }

        public async static Task<string> DeleteAsync(string url)
        {
            AuthenticationResult result = await ReturnAuthenticationResult();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.DeleteAsync(url);
            try
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                return null;
            }

        }

        public async static Task<string> PutAsync(string url, HttpContent content)
        {
            AuthenticationResult result = await ReturnAuthenticationResult();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.PutAsync(url, content);
            try
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                return null;
            }

        }

        public async static Task<string> PostAsync(string url, HttpContent content)
        {

            AuthenticationResult result = await ReturnAuthenticationResult();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.PostAsync(url, content);
            try
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                return null;
            }

        }
    }
}
```

### Actions.cs

```csharp
using LakeHouseFileDirectoryOperations;
using Microsoft.Identity.Client;
using Newtonsoft.Json.Linq;
using Security;
using Spectre.Console;
using System.Net.Http.Headers;
using System.Text;

namespace Action
{
    public class Actions
    {
        public static async Task _DeleteDirectory(string directoryfullpath)
        {

            Program.dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{directoryfullpath}?restype=directory&recursive=true";
            try
            {
                await Http.HttpMethods.DeleteAsync(Program.dfsendpoint);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Directory deletion failed : " + ex.Message);
            }
        }

        public static async Task UploadFilesToLakeHouse(string uploadpath, string lakehousedirectory)
        {

            DirectoryInfo d = new DirectoryInfo(uploadpath);
            byte[] bytes;

            foreach (FileInfo file in d.GetFiles())
            {
                using (Stream stream = File.OpenRead(file.FullName))
                {
                    string RequestUri = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{lakehousedirectory}/{file.Name}?resource=file";
                    string jsonString = System.String.Empty;
                    var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
                    var response = await Http.HttpMethods.PutAsync(RequestUri, content);
                    await FileStreamSendAsync(stream, lakehousedirectory, file.Name);
                }

            }

        }

        public static async Task DownloadFilesFromLakeHouse(string lakehouse_directoryfullpath, string local_directoryfullpath)
        {
            string dfsendpoint = "";

            dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{lakehouse_directoryfullpath}";

            var downloadMessage = new HttpRequestMessage
            {
                Method = HttpMethod.Get,
                RequestUri = new Uri(dfsendpoint)
            };

            try
            {
                var response_d = await Http.HttpMethods.SendAsync(downloadMessage);
                string filename_n = await GetDirectoryName(lakehouse_directoryfullpath);
                File.WriteAllBytes($"{local_directoryfullpath}\\{filename_n}", response_d);
            }
            catch (Exception ex)
            {
                Console.WriteLine("File download failed : " + ex.Message);

            }

        }

       public async static Task<string> FileStreamSendAsync(Stream stream, string directory, string filename)
        {
            AuthenticationResult result = await Authentication.ReturnAuthenticationResult();

            Security.Authentication.client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

            var content = new StreamContent(stream);
            string url = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{directory}/{filename}?action=append&position=0";
            var streamMessage = new HttpRequestMessage
            {
                Method = HttpMethod.Patch,
                RequestUri = new Uri(url),
                Content = content
            };
            HttpResponseMessage response = await Http.HttpMethods.client.SendAsync(streamMessage);

            try
            {
                response.EnsureSuccessStatusCode();
                await response.Content.ReadAsStringAsync();
            }
            catch
            {
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
                return null;
            }
            if (response.IsSuccessStatusCode)
            {
                url = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{directory}/{filename}?action=flush&position={stream.Length}";
                Http.HttpMethods.client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                var flushMessage = new HttpRequestMessage
                {
                    Method = HttpMethod.Patch,
                    RequestUri = new Uri(url)
                };
                response = await Http.HttpMethods.client.SendAsync(flushMessage);
                response.EnsureSuccessStatusCode();
            }
            return null;
        }

        public static async Task Create_Directory(string directoryfullpath)
        {
            string jsonString = System.String.Empty;
            Program.dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{directoryfullpath}?resource=directory";
            var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
            try
            {
                await Http.HttpMethods.PutAsync(Program.dfsendpoint, content);
                AnsiConsole.MarkupLine("");
                AnsiConsole.MarkupLine($"[blue]Success[/] : Directory [Yellow]{await GetDirectoryName(directoryfullpath)}[/] successfully created in lakehouse : [Yellow]{Program.lakeHouse}[/]");
                Thread.Sleep(1000);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Directory creation failed : " + ex.Message);

            }
        }


        public static async Task Rename_Directory(string old_directoryfullpath, string new_directoryfullpath)
        {
            Program.dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{new_directoryfullpath}?restype=directory&comp=rename";
            var Metadata = new HttpRequestMessage
            {
                Method = HttpMethod.Put,
                RequestUri = new Uri(Program.dfsendpoint)
            };
            Metadata.Headers.Add("x-ms-rename-source", $"/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{old_directoryfullpath}");

            try
            {
                await Http.HttpMethods.SendAsync(Metadata);
                AnsiConsole.MarkupLine("");
                AnsiConsole.MarkupLine($"[blue]Success[/] : Directory [Yellow]{await GetDirectoryName(old_directoryfullpath)}[/] successfully renamed to [Yellow]{await GetDirectoryName(new_directoryfullpath)}[/] in lakehouse : [Yellow]{Program.lakeHouse}[/]");
                Thread.Sleep(1000);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Directory rename failed : " + ex.Message);

            }
        }

        public static async Task<string> GetDirectoryName(string value)
        {
            int lastSlashIndex_n = value.ToString().LastIndexOf('/');
            string dir_n = value.ToString().Substring(lastSlashIndex_n + 1);
            return dir_n;
        }


        public static async Task<JObject> TraverseAllLakeHousesInWorkspace(string workspace)
        {
            string dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{workspace}" + $"?resource=filesystem&recursive=false";
            string response = await Http.HttpMethods.GetAsync(dfsendpoint);
            if (response == null)
            {
                return null;
            }
            else
            {
                JObject jsonObject_lakehouse = JObject.Parse(response);
                return jsonObject_lakehouse;
            }
        }

        public static async Task<SelectionPrompt<string>> TraverseAllDirectoriesInLakeHouse(string lakehouse)
        {
            int i = 1;
            string dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/Files?resource=filesystem&recursive=true";
            string response = await Http.HttpMethods.GetAsync(dfsendpoint);
            JObject jsonObject_dir = JObject.Parse(response);
            JArray dirArray = (JArray)jsonObject_dir["paths"];
            var prompt = new SelectionPrompt<string>();
            prompt.AddChoice($"{i}.\tFiles");
            i = i + 1;
            foreach (JObject dir in dirArray)
            {
                if (dir["isDirectory"] != null)
                {
                    int lastSlashIndex_n = dir["name"].ToString().IndexOf('/');
                    string dir_n = dir["name"].ToString().Substring(lastSlashIndex_n + 1);
                    prompt.AddChoice($"{i}.\t{dir_n.ToString()}"); i++;
                }
            }

            return prompt;
        }

        public static async Task<MultiSelectionPrompt<string>> TraverseAllFilesInDirectories(string directorypath)
        {
            if (directorypath == "" && Program.Dir != "")
            {
                int tabIndex = Program.Dir.IndexOf('\t');
                directorypath = Program.Dir.Substring(tabIndex + 1);
            }
            string dfsendpoint = $"https://onelake.dfs.fabric.microsoft.com/{Program.workSpace}/{Program.lakeHouse}.Lakehouse/{directorypath}?resource=filesystem&recursive=false";
            string response = await Http.HttpMethods.GetAsync(dfsendpoint);
            JObject jsonObject_dir = JObject.Parse(response);
            JArray dirArray = (JArray)jsonObject_dir["paths"];
            var prompt = new MultiSelectionPrompt<string>();
            List<string> lst = new List<string>();

            foreach (JObject dir in dirArray)
            {
                if (dir["isDirectory"] == null)
                {
                    // prompt.AddChoices(await GetDirectoryName(dir["name"].ToString());
                    //   prompt.AddChoiceGroup("Files",await GetDirectoryName(dir["name"].ToString()));
                    lst.Add(await GetDirectoryName(dir["name"].ToString()));
                }
            }
            if (lst.Count > 0) { prompt.AddChoiceGroup("File List", lst); }
            prompt.AddChoice("[red]<< Back To Directory List >>[/]");
            return prompt;
        }

    }
}
```

### Program.cs

```csharp
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using Security;
using Spectre.Console;

namespace LakeHouseFileDirectoryOperations
{
    public class Program : Action.Actions
    {
        private static string DownloadLocation = "";
        public static string workSpace = "";
        public static string lakeHouse = "";
        public static string dfsendpoint = "";
        public static string operation = "";
        public static string Dir = "";
        public static string Filepath = "";
        public static string selectedOption = "";
        public static string currlakehouse = "";
        public static async Task Main(string[] args)
        {

            ReadConfig();
            await ConfirmWorkspace();
            while (Dir.Contains("Files") || Dir.Contains("Back To Lakehouse"))
            {
                AnsiConsole.Clear(); Header(); CurrentWorkspaceLakehouse();
                await MainMenu(selectedOption);
            }

        }

        public static void ReadConfig()
        {
            var builder = new ConfigurationBuilder()
            .AddJsonFile($"appsettings.json", true, true);
            var config = builder.Build();
            Security.Authentication.clientId = config["ClientId"];
            DownloadLocation = config["DownloadLocation"];
        }
        public static void Header()
        {
            Console.Title = "Microsoft Fabric Command Line";
            AnsiConsole.MarkupLine($".NET Version: [blue]{Environment.Version.ToString()}[/]");
            AnsiConsole.Write(
               new FigletText("Microsoft Fabric Command Line Tool")
            .Centered()
            .Color(Color.Red));
        }

        public async static Task ConfirmWorkspace()
        {
            Header();
            AnsiConsole.MarkupLine("");
            workSpace = AnsiConsole.Prompt(
            new TextPrompt<string>("Please Enter the Workspace : "));
            AnsiConsole.MarkupLine("");
            var confirmation_1 = AnsiConsole.Prompt(
            new TextPrompt<bool>($"Is the workspace [Yellow]{workSpace}[/] that you want to use ?")
           .AddChoice(true)
           .AddChoice(false)
           .DefaultValue(true)
           .WithConverter(choice => choice ? "yes" : "no"));
            string str = confirmation_1 ? "Confirmed" : "Declined";
            if (str == "Declined")
            { AnsiConsole.Clear(); await ConfirmWorkspace(); }
            else await MainMenu("");
        }

        public static void CurrentWorkspaceLakehouse()
        {

            AnsiConsole.MarkupLine($"Your current workspace is [Yellow]{workSpace}[/] and lakehouse is [Yellow]{lakeHouse}[/] ");
            AnsiConsole.MarkupLine("");
        }
        public async static Task DisplayLakehouses()
        {

            int i = 1;
            JObject jobject = await TraverseAllLakeHousesInWorkspace(workSpace);
            if (jobject == null)
            {
                AnsiConsole.MarkupLine($"Your current workspace [red]{workSpace}[/] is invalid ");
                Thread.Sleep(2500);
                AnsiConsole.Clear();
                await ConfirmWorkspace();

            };
            var lkhouse = new List<string>();
            AnsiConsole.Status()
                .Start($"Getting a list of lakehouses from the workspace [Yellow]{workSpace}[/]...", ctx =>
                {

                    ctx.Spinner(Spinner.Known.Star);
                    ctx.SpinnerStyle(Style.Parse("Yellow"));
                    JArray pathsArray = (JArray)jobject["paths"];

                    foreach (JObject path in pathsArray)
                    {
                        if (path["name"].ToString().Contains(".Lakehouse"))
                        {
                            lkhouse.Add(path["name"].ToString().Replace(".Lakehouse", ""));
                        }
                    }
                    Thread.Sleep(1500);
                    ctx.Status("Done ..");
                    Thread.Sleep(1000);

                });

            var prompt = new SelectionPrompt<string>();

            foreach (var obj in lkhouse)
            {
                prompt.AddChoice($"{i}.\t{obj.ToString()}"); i++;

            }
            prompt.AddChoice($"[red]{""} \t<< Main Menu >>[/]");
            AnsiConsole.Clear();
            Header();
            AnsiConsole.MarkupLine($"Your current workspace is [Yellow]{workSpace}[/]");
            AnsiConsole.MarkupLine("");
            prompt.Title("Which lakehouse would you like to interact with ?")
                    .PageSize(30)
                    .MoreChoicesText("[grey](Move up and down to reveal more)[/]");

            lakeHouse = AnsiConsole.Prompt(prompt);
            lakeHouse = lakeHouse.Replace(lakeHouse.Substring(0, lakeHouse.IndexOf("\t") + 1), "");

            if (lakeHouse.Contains("Main Menu"))
            { await MainMenu(""); }

        }
        public static async Task<SelectionPrompt<string>> MiscOperationsInPrompt(string operation)
        {
            var dirprompt = new SelectionPrompt<string>();
            if (Dir == "") { await DisplayLakehouses(); }
            AnsiConsole.Clear();
            Header();
            dirprompt = await TraverseAllDirectoriesInLakeHouse(lakeHouse);
            dirprompt.AddChoice("[red]<< Back To Lakehouse List >>[/]");
            dirprompt.Title("Which directory would you like to interact with ?")
                   .PageSize(30)
                   .MoreChoicesText("[grey](Move up and down to reveal more lakehouses)[/]");
            AnsiConsole.MarkupLine($"Your current workspace is [Yellow]{workSpace}[/] and lakehouse is [Yellow]{lakeHouse}[/] ");
            AnsiConsole.MarkupLine("");
            return dirprompt;
        }

        public static async Task<string> ListOperationsInPrompt(string operation)
        {
            var dirprompt_s = new SelectionPrompt<string>();
            var dirprompt_m = new MultiSelectionPrompt<string>();
            string title = "";
            if (!Dir.Contains("Files"))
            {

                if (operation == "1.\tLakeHouse directory structure")
                {

                    title = "Select the directory to view its structure";
                }

                if (operation == "2.\tCreate a lakehouse directory")
                {

                    title = "Which location would you like to create a directory ?";
                }

                if (operation == "3.\tRename a lakehouse directory")
                {

                    title = "Which directory would you like to rename ?";
                }

                if (operation == "4.\tDelete a lakehouse directory")
                {

                    title = "Which directory would you like to delete ?";
                }

                if (operation == "5.\tDownload files from a lakehouse directory")
                {

                    title = "Files from which directory would you like to download ?";

                }
                if (operation == "6.\tUpload files to a lakehouse directory")
                {

                    title = "Directory to which files to be uploaded";

                }
                if (Dir.Contains("Back To Lakehouse List"))
                { await DisplayLakehouses(); }
                dirprompt_s = await MiscOperationsInPrompt(operation);
                dirprompt_s.Title(title)
                       .PageSize(30)
                       .MoreChoicesText("[grey](Move up and down to reveal more directories)[/]");
                Dir = AnsiConsole.Prompt(dirprompt_s);

            }
            return Dir;
        }

        public static async Task<string> ReturnFileName()
        {
            int tabIndex = Dir.IndexOf('\t');
            return Dir.Substring(tabIndex + 1);
        }

        public static async Task MainMenu(string operation)
        {

            const string LakeHouseStructure = "1.\tLakeHouse directory structure";
            const string CreateDirectory = "2.\tCreate a lakehouse directory";
            const string RenameDirectory = "3.\tRename a lakehouse directory";
            const string DeleteDirectory = "4.\tDelete a lakehouse directory";
            const string DownloadFiles = "5.\tDownload files from a lakehouse directory";
            const string UploadFiles = "6.\tUpload files to a lakehouse directory";
            const string ChangeWorkspace = "7.\tChange Workspace";
            const string exit = "8.\tExit this Application";

            AnsiConsole.Clear();
            Header();
            AnsiConsole.MarkupLine($"Your current workspace is [Yellow]{workSpace}[/]");
            AnsiConsole.MarkupLine("");
            selectedOption = "";
            if (operation == "")
            {
                selectedOption = AnsiConsole.Prompt(
               new SelectionPrompt<string>()
                 .Title("Select an option to continue")
                 .PageSize(30)
                 .MoreChoicesText("[grey](Move up and down to reveal more options)[/]")
                 .AddChoices(new[] {
                           LakeHouseStructure,CreateDirectory,RenameDirectory,DeleteDirectory,DownloadFiles,UploadFiles,ChangeWorkspace,exit
                 }));
            }
            else
            {
                selectedOption = operation;
            }

            if (Authentication.istokencached == false)
            {
                AnsiConsole.Clear();
                Header();
                AnsiConsole.MarkupLine("[red]Note[/] : You will be prompted in a new browser window to enter the credentials of your fabric tenant!!!");
                Thread.Sleep(1500);

            }

            var fileprompt_m = new MultiSelectionPrompt<string>();
            var dirprompt_s = new SelectionPrompt<string>();
            switch (selectedOption)
            {

                case LakeHouseStructure:
                    operation = "1.\tLakehouse directory structure";
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    if (Dir == "Main Menu" || Dir.Contains("Back To Lakehouse")) { Dir = ""; await MainMenu(operation); }
                    else
                    {
                        Filepath = await ReturnFileName();
                        fileprompt_m = await TraverseAllFilesInDirectories(Filepath.ToString());
                        var filename_d = AnsiConsole.Prompt(fileprompt_m);
                    }
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    await ListOperationsInPrompt(operation);
                    break;

                case CreateDirectory:
                    operation = "2.\tCreate a lakehouse directory";
                    Dir = await ListOperationsInPrompt(operation);
                    if (Dir == "Main Menu" || Dir.Contains("Back To Lakehouse")) { Dir = ""; await MainMenu(operation); }
                    else

                    {
                        Filepath = await ReturnFileName();
                        var new_dir_n = AnsiConsole.Prompt(
                           new TextPrompt<string>(($"Enter the name for the new directory in [Yellow]{Filepath}[/] : ")));
                        await Create_Directory($"{Filepath}/{new_dir_n}");

                    };
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    await ListOperationsInPrompt(operation);

                    break;

                case RenameDirectory:
                    operation = "3.\tRename a lakehouse directory";
                    Dir = await ListOperationsInPrompt(operation);
                    if (Dir == "Main Menu") { await MainMenu("RenameDirectory"); }
                    if (Dir.Contains("Back To Lakehouse")) { Dir = ""; await TraverseAllLakeHousesInWorkspace(workSpace); }

                    else
                    {
                        int lastSlashIndex = Dir.ToString().LastIndexOf('\t');
                        string dir_n = Dir.ToString().Substring(lastSlashIndex + 1);

                        if (Dir == "1.	Files")
                        {
                            AnsiConsole.MarkupLine($"Cannot rename directory [Yellow]{dir_n}[/]");
                            Thread.Sleep(2000);
                        }
                        else
                        {
                            var new_dir_n = AnsiConsole.Prompt(
                             new TextPrompt<string>(($"Enter the new name for the directory [Yellow]{dir_n}[/] : ")));

                            int index = Dir.IndexOf(dir_n);
                            lastSlashIndex = Dir.ToString().LastIndexOf('/');
                            if (index != -1)
                            {

                                Filepath = await ReturnFileName();
                                int tabIndex = (Dir.Substring(0, lastSlashIndex + 1) + new_dir_n).IndexOf('\t');
                                string newFile = (Dir.Substring(0, lastSlashIndex + 1) + new_dir_n).Substring(tabIndex + 1);
                                await Rename_Directory(Filepath, newFile);
                            }
                        }
                    };
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    await ListOperationsInPrompt(operation);
                    break;

                case DeleteDirectory:

                    operation = "4.\tDelete a lakehouse directory";

                    Dir = await ListOperationsInPrompt(operation);

                    if (Dir == "Main Menu")
                    { await MainMenu("DeleteDirectory"); }

                    if (Dir.Contains("Back To Lakehouse") || Dir == "")
                    {
                        Dir = ""; await MainMenu("");
                        break;
                    }

                    else
                    {
                        Filepath = await ReturnFileName();

                        var confirmation = AnsiConsole.Prompt(
                         new TextPrompt<bool>($"Are you sure you want to delete this directory ?")
                        .AddChoice(true)
                        .AddChoice(false)
                        .DefaultValue(true)
                        .WithConverter(choice => choice ? "yes" : "no"));

                        if (confirmation == true)
                        {
                            await _DeleteDirectory(Filepath);
                            AnsiConsole.MarkupLine("");
                            AnsiConsole.MarkupLine($"Successfully deleted directory [Yellow]{await GetDirectoryName(Dir)}[/]");
                            Thread.Sleep(2000);
                            dirprompt_s = await MiscOperationsInPrompt(operation);
                            Dir = AnsiConsole.Prompt(dirprompt_s);
                            await ListOperationsInPrompt(operation);
                            break;
                        }

                        else
                        {
                            Dir = ""; await MainMenu(operation);
                            break;
                        }

                    }

                case DownloadFiles:

                    operation = "5.\tDownload files from a lakehouse directory";
                    if (Dir == "")
                    {
                        Dir = await ListOperationsInPrompt(operation);
                    }
                    if (Dir.Contains("Back To Lakehouse"))
                    {
                        Dir = await ListOperationsInPrompt(operation);
                    }

                    var filename = new List<string>();
                    Filepath = await ReturnFileName();
                    fileprompt_m = await TraverseAllFilesInDirectories(Filepath.ToString());

                    filename = AnsiConsole.Prompt(fileprompt_m);
                    int i = 0; int j = 0;
                    foreach (string flname in filename)
                    {
                        if (flname.ToString().Contains("Back To Directory"))
                        {
                            if (i > 0)
                            {
                                AnsiConsole.MarkupLine("");
                                AnsiConsole.MarkupLine($"[Yellow]All files downloaded succesfully[/]");
                                Thread.Sleep(2000);
                                AnsiConsole.Clear();
                                Header();
                                CurrentWorkspaceLakehouse();
                                j = 1;
                            }
                        }
                        else
                        {
                            i++;
                            int tabIndex = Dir.IndexOf('\t');
                            Filepath = Dir.Substring(tabIndex + 1);
                            await DownloadFilesFromLakeHouse(Filepath + "//" + flname, DownloadLocation);

                        }

                    }
                    if (i > 0 && j == 0)
                    {
                        AnsiConsole.MarkupLine("");
                        AnsiConsole.MarkupLine($"All files downloaded succesfully from [Yellow]{Filepath}[/] to [Yellow]{DownloadLocation}[/]");
                        Thread.Sleep(2000);
                        AnsiConsole.Clear();
                        Header();
                        CurrentWorkspaceLakehouse();
                    }
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    await ListOperationsInPrompt(operation);
                    break;

                case ChangeWorkspace:

                    AnsiConsole.Clear();
                    await ConfirmWorkspace();
                    break;

                case UploadFiles:

                    operation = "6.\tUpload files to a lakehouse directory";

                    Dir = await ListOperationsInPrompt(operation);

                    if (Dir == "Main Menu" || Dir.Contains("Back To Lakehouse"))
                    {
                        Dir = ""; await MainMenu(operation);
                    }
                    else
                    {
                        Filepath = await ReturnFileName();
                        var local_dir_n = AnsiConsole.Prompt(
                           new TextPrompt<string>(($"Enter the local path : ")));
                        await UploadFilesToLakeHouse(local_dir_n, Filepath);
                    };
                    AnsiConsole.MarkupLine("");
                    AnsiConsole.MarkupLine($"All files uploaded succesfully to [Yellow]{Filepath}[/]");
                    Thread.Sleep(2000);
                    AnsiConsole.Clear();
                    Header();
                    CurrentWorkspaceLakehouse();
                    AnsiConsole.MarkupLine($"Uploaded files in [Yellow]{Filepath}[/]");
                    AnsiConsole.MarkupLine("");
                    Filepath = await ReturnFileName();
                    fileprompt_m = await TraverseAllFilesInDirectories(Filepath.ToString());
                    filename = AnsiConsole.Prompt(fileprompt_m);
                    dirprompt_s = await MiscOperationsInPrompt(operation);
                    Dir = AnsiConsole.Prompt(dirprompt_s);
                    await ListOperationsInPrompt(operation);
                    break;

                case exit:
                    await ExitApplication();
                    return;
            }

        }

        public static async Task ExitApplication()
        {
            AnsiConsole.MarkupLine("");
            var confirmation_3 = AnsiConsole.Prompt(
              new TextPrompt<bool>($"Are you sure you want to exit the application ?")
             .AddChoice(true)
             .AddChoice(false)
             .DefaultValue(true)
             .WithConverter(choice => choice ? "yes" : "no"));
            if (confirmation_3 == true)
            { Environment.Exit(0); }

        }
    }
}
```

### Conclusion :

The main idea behind this console app was to explore the possibility of managing Fabric components outside the Fabric environment. In the upcoming articles I will be demonstrating a few other aspects of fabric artifacts that can be managed outside the Fabric environment.

Thanks for reading !!!
