protected internal override void Execute()
        {
            CommandBuild.ConfigServerPublish();

            ConfigCli configCli         = ConfigCli.Load();
            string    deployAzureGitUrl = UtilFramework.StringNull(configCli.EnvironmentGet().DeployAzureGitUrl); // For example: "https://*****:*****@my22.scm.azurewebsites.net:443/my22.git"

            if (deployAzureGitUrl == null)
            {
                UtilCli.ConsoleWriteLineColor(nameof(ConfigCliEnvironment.DeployAzureGitUrl) + " not set!", System.ConsoleColor.Green);
            }
            else
            {
                string folderName           = UtilFramework.FolderName + "Application.Server/";
                string folderNamePublish    = UtilFramework.FolderName + "Application.Server/bin/Debug/net5.0/publish/";
                string folderNamePublishGit = folderNamePublish + ".git";

                UtilCli.FolderDelete(folderNamePublishGit);                                            // Undo git init.
                UtilCli.Start(folderNamePublish, "git", "init -b master");                             // External system to push to.
                UtilCli.Start(folderNamePublish, "git", "config user.email \"[email protected]\""); // Prevent: Error "Please tell me who you are". See also: http://www.thecreativedev.com/solution-github-please-tell-me-who-you-are-error/
                UtilCli.Start(folderNamePublish, "git", "config user.name \"Deploy\"");
                UtilCli.Start(folderNamePublish, "git", "config core.autocrlf false");                 // Prevent "LF will be replaced by CRLF" error in stderr.
                UtilCli.Start(folderNamePublish, "git", "add .");                                      // Can throw "LF will be replaced by CRLF".
                UtilCli.Start(folderNamePublish, "git", "commit -m Deploy");
                UtilCli.Start(folderNamePublish, "git", "remote add azure " + deployAzureGitUrl);
                UtilCli.Start(folderNamePublish, "git", "push azure master -f", isRedirectStdErr: true); // Do not write to stderr. Can be tested with "dotnet run -- deploy [DeployAzureGitUrl] 2>Error.txt"
            }
        }
Beispiel #2
0
        /// <summary>
        /// Set default values if file ConfigCli.json does not exist.
        /// </summary>
        protected override void InitConfigCli(ConfigCli configCli)
        {
            string appTypeName = UtilCli.AppTypeName(typeof(AppMain));

            configCli.WebsiteList.Add(new ConfigCliWebsite()
            {
                DomainNameList = new List <ConfigCliWebsiteDomain>(new ConfigCliWebsiteDomain[] { new ConfigCliWebsiteDomain {
                                                                                                      EnvironmentName = "DEV", DomainName = "localhost", AppTypeName = appTypeName, PasswordSalt = UtilFramework.PasswordSaltConfigCreate()
                                                                                                  } }),
                FolderNameAngular = "Application.Website/",
            });

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // Default ConnectionString (Windows)
                configCli.EnvironmentGet().ConnectionStringApplication = "Data Source=localhost\\SQLEXPRESS; Initial Catalog=ApplicationDoc; Integrated Security=True;";
                configCli.EnvironmentGet().ConnectionStringFramework   = "Data Source=localhost\\SQLEXPRESS; Initial Catalog=ApplicationDoc; Integrated Security=True;";
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                // Default ConnectionString (Linux)
                configCli.EnvironmentGet().ConnectionStringApplication = "Data Source=localhost; Initial Catalog=ApplicationDoc; User Id=SA; Password=MyPassword;";
                configCli.EnvironmentGet().ConnectionStringFramework   = "Data Source=localhost; Initial Catalog=ApplicationDoc; User Id=SA; Password=MyPassword;";
            }
        }
Beispiel #3
0
        /// <summary>
        /// Build all layout Websites. For example: "Application.Website/LayoutDefault"
        /// </summary>
        private void BuildWebsite()
        {
            var configCli = ConfigCli.Load();

            // Ensure FolderNameNpmBuild is defined once only in ConfigCli.json.
            ConfigCliWebsite configCliWebsite = configCli.WebsiteList.GroupBy(item => item.FolderNameNpmBuild.ToLower()).Where(group => group.Count() > 1).FirstOrDefault()?.FirstOrDefault();

            UtilFramework.Assert(configCliWebsite == null, string.Format("ConfigCli.json Website defined more than once. Use DomainNameList instead! (FolderNameNpmBuild={0})", configCliWebsite?.FolderNameNpmBuild));

            // Delete folder Application.Server/Framework/Application.Website/
            string folderNameApplicationWebsite = UtilFramework.FolderName + "Application.Server/Framework/Application.Website/";

            UtilCli.FolderDelete(folderNameApplicationWebsite);

            foreach (var website in configCli.WebsiteList)
            {
                Console.WriteLine(string.Format("### Build Website (Begin) - {0}", website.DomainNameListToString()));

                // Delete dist folder
                string folderNameDist = UtilFramework.FolderNameParse(website.FolderNameDist);
                UtilFramework.Assert(folderNameDist != null);
                UtilCli.FolderDelete(folderNameDist);

                // npm run build
                BuildWebsiteNpm(website);
                string folderNameServer = UtilFramework.FolderNameParse("Application.Server/Framework/" + website.FolderNameDist);
                UtilFramework.Assert(folderNameServer != null, "FolderNameServer can not be null!");
                UtilFramework.Assert(folderNameServer.StartsWith("Application.Server/Framework/Application.Website/"), "FolderNameServer has to start with 'Application.Server/Framework/Application.Website/'!");

                // Copy dist folder
                string folderNameSource = UtilFramework.FolderName + folderNameDist;
                string folderNameDest   = UtilFramework.FolderName + folderNameServer;
                if (!UtilCli.FolderNameExist(folderNameSource))
                {
                    throw new Exception(string.Format("Folder does not exist! ({0})", folderNameDest));
                }

                // Layout file main.js and Angular file main.js
                // Prevent for example two main.js. Angular js can not be overridden by layout Website
                // Application.Website/LayoutDefault/dist/main.js
                // Application.Server/Framework/Framework.Angular/browser/main.js
                var fileNameList = new string[] { "runtime.js", "polyfills.js", "main.js" };
                foreach (var fileName in fileNameList)
                {
                    var fileNameFull = folderNameSource + fileName;
                    if (File.Exists(fileNameFull))
                    {
                        throw new Exception(string.Format("File conflicts with Angular! See also: https://webpack.js.org/configuration/output/ ({0})", fileNameFull));
                    }
                }

                UtilCli.FolderDelete(folderNameDest);
                UtilFramework.Assert(!UtilCli.FolderNameExist(folderNameDest));
                UtilCli.FolderCopy(folderNameSource, folderNameDest, "*.*", true);
                UtilFramework.Assert(UtilCli.FolderNameExist(folderNameDest));

                Console.WriteLine(string.Format("### Build Website (End) - {0}", website.DomainNameListToString()));
            }
        }
Beispiel #4
0
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string connectionString = ConfigCli.ConnectionString(IsFrameworkDb);

            UtilFramework.Assert(string.IsNullOrEmpty(connectionString) == false, "ConnectionString is null!");
            optionsBuilder.UseSqlServer(connectionString);
            optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        }
Beispiel #5
0
        protected internal override void Execute()
        {
            // Build angular client
            if (!UtilCli.FolderNameExist(UtilFramework.FolderName + "Application.Server/Framework/Framework.Angular/"))
            {
                var commandBuild = new CommandBuild(AppCli);
                UtilCli.OptionSet(ref commandBuild.OptionClientOnly, true);
                commandBuild.Execute();
            }

            if (optionWatch.OptionGet())
            {
                ConfigCli configCli = ConfigCli.Load();

                var website = configCli.WebsiteList.First(item => item.FolderNameDist != null); // TODO choose if multiple

                string folderNameNpmBuilt = UtilFramework.FolderName + website.FolderNameNpmBuild;
                string folderNameDist     = UtilFramework.FolderName + website.FolderNameDist;

                string folderNameAngular         = UtilFramework.FolderName + "Framework/Framework.Angular/application/";
                string folderNameCustomComponent = UtilFramework.FolderName + "Application.Website/Shared/CustomComponent/";

                UtilCli.ConsoleWriteLineColor("Port: http://localhost:4200/", System.ConsoleColor.Green);
                UtilCli.ConsoleWriteLineColor("Website: " + folderNameNpmBuilt, System.ConsoleColor.Green);
                UtilCli.ConsoleWriteLineColor("CustomComponent: " + folderNameCustomComponent, System.ConsoleColor.Green);
                UtilCli.ConsoleWriteLineColor("Framework: " + folderNameAngular, System.ConsoleColor.Green);

                FileSync fileSync = new FileSync();
                fileSync.AddFolder(folderNameDist, folderNameAngular + "src/Application.Website/Default/"); // TODO
                fileSync.AddFolder(folderNameCustomComponent, folderNameAngular + "src/Application.Website/Shared/CustomComponent/");

                UtilCli.Npm(folderNameNpmBuilt, "run build -- --watch", isWait: false);
                UtilCli.Npm(folderNameAngular, "start", isWait: true);
            }
            else
            {
                string folderName = UtilFramework.FolderName + @"Application.Server/";
                UtilCli.VersionBuild(() =>
                {
                    UtilCli.DotNet(folderName, "build");
                });
                UtilCli.DotNet(folderName, "run --no-build", false);
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    UtilCli.OpenWebBrowser("http://localhost:50919/"); // For port setting see also: Application.Server\Properties\launchSettings.json (applicationUrl, sslPort)
                }
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    // Ubuntu list all running processes: 'ps'
                    // To reboot Ubuntu type on Windows command prompt: 'wsl -t Ubuntu-18.04'
                    // Ubuntu show processes tool: 'htop'
                    UtilCli.ConsoleWriteLineColor("Stop server with command: 'killall -SIGKILL Application.Server node dotnet'", System.ConsoleColor.Yellow);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Copy ConfigCli.json to ConfigServer.json and validate ConnectionString exists.
        /// </summary>
        private void CopyConfigCliToConfigServer()
        {
            ConfigCli.CopyConfigCliToConfigServer();
            var configCli   = ConfigCli.Load();
            var environment = configCli.EnvironmentGet();

            if (UtilFramework.StringNull(environment.ConnectionStringFramework) == null || UtilFramework.StringNull(environment.ConnectionStringFramework) == null)
            {
                UtilCli.ConsoleWriteLineColor(string.Format("No ConnectionString for {0}! Set it with command cli config connectionString.", environment.EnvironmentName), ConsoleColor.Yellow);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Write config ConnectionStringFramework and ConnectionStringApplication to ConfigCli.json and ConfigServer.json.
        /// </summary>
        private void ArgumentConnectionString()
        {
            ConfigCli configCli = ConfigCli.Load();

            if (UtilCli.ArgumentValue(this, argumentConnectionString, out string connectionString))
            {
                // Write
                configCli.EnvironmentGet().ConnectionStringFramework   = connectionString;
                configCli.EnvironmentGet().ConnectionStringApplication = connectionString;
                ConfigCli.Save(configCli);
            }
        }
Beispiel #8
0
        protected internal override void Execute()
        {
            ConfigCli configCli = ConfigCli.Load();

            if (optionSilent.OptionGet() == false && configCli.EnvironmentNameGet() != "DEV")
            {
                if (UtilCli.ConsoleReadYesNo(string.Format("Deploy to {0} database?", configCli.EnvironmentName)) == false)
                {
                    return;
                }
            }

            if (optionDrop.OptionGet())
            {
                // FolderNameDeployDb
                string folderNameDeployDbFramework   = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDb/";
                string folderNameDeployDbApplication = UtilFramework.FolderName + "Application.Cli/DeployDb/";

                Console.WriteLine("DeployDbDrop");
                DeployDbDropExecute(folderNameDeployDbApplication, isFrameworkDb: false);
                DeployDbDropExecute(folderNameDeployDbFramework, isFrameworkDb: true); // Uses ConnectionString in ConfigServer.json

                UtilCli.ConsoleWriteLineColor("DeployDb drop successful!", ConsoleColor.Green);
            }
            else
            {
                // FolderNameDeployDb
                string folderNameDeployDbFramework   = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDb/";
                string folderNameDeployDbApplication = UtilFramework.FolderName + "Application.Cli/DeployDb/";

                // SqlInit
                string fileNameInit = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDbInit/Init.sql";
                string sqlInit      = UtilFramework.FileLoad(fileNameInit);
                Data.ExecuteNonQueryAsync(sqlInit, null, isFrameworkDb: true).Wait();

                // (*.sql)
                UtilCli.ConsoleWriteLineColor("DeployDb run (*.sql) scripts", ConsoleColor.Green);
                DeployDbExecute(folderNameDeployDbFramework, isFrameworkDb: true); // Uses ConnectionString in ConfigServer.json
                DeployDbExecute(folderNameDeployDbApplication, isFrameworkDb: false);
                UtilCli.ConsoleWriteLineColor("DeployDb run (*.sql) scripts successful!", ConsoleColor.Green);

                // Integrate
                UtilCli.ConsoleWriteLineColor("DeployDb run Integrate", ConsoleColor.Green);
                int?reseed = null;
                if (optionReseed.OptionGet())
                {
                    reseed = 1000;
                }
                Integrate(reseed);
                UtilCli.ConsoleWriteLineColor("DeployDb run Integrate successful!", ConsoleColor.Green);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Write text which might contain sensitive data (ConnectionString and GitUrl) with this method to console.
        /// </summary>
        internal static void ConsoleWriteLinePassword(object value, ConsoleColor?color = null)
        {
            string text        = string.Format("{0}", value);
            var    configCli   = ConfigCli.Load();
            var    environment = configCli.EnvironmentGet();

            text = ConsoleWriteLinePasswordHide(text, environment.ConnectionStringFramework);
            text = ConsoleWriteLinePasswordHide(text, environment.ConnectionStringApplication);
            text = ConsoleWriteLinePasswordHide(text, environment.DeployAzureGitUrl);
            text = ConsoleWriteLinePasswordHide(text, configCli.ExternalGit);

            text = text.Replace("{", "{{").Replace("}", "}}"); // Console.Write("{", ConsoleColor.Green); throws exception "Input string was not in a correct format". // TODO Bug report

            Console.WriteLine(text, color);
        }
Beispiel #10
0
        /// <summary>
        /// Read or write config ConnectionStringApplication.
        /// </summary>
        private void ArgumentConnectionStringApplication()
        {
            ConfigCli configCli = ConfigCli.Load();

            if (UtilCli.ArgumentValue(this, argumentConnectionStringApplication, out string connectionString))
            {
                // Write
                configCli.EnvironmentGet().ConnectionStringApplication = connectionString;
                ConfigCli.Save(configCli);
            }
            else
            {
                // Read
                UtilCli.ConsoleWriteLinePassword(argumentConnectionStringApplication.Name + "=" + configCli.EnvironmentGet().ConnectionStringApplication);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Run method AppCli.CommandExternal(); on ExternalGit/ProjectName/
        /// </summary>
        private static void CommandExternal()
        {
            var configCli = ConfigCli.Load();

            // External git url
            var externalGit = UtilFramework.StringNull(configCli.ExternalGit);

            // Call command cli external (prebuild script)
            var externalProjectName = UtilFramework.StringNull(configCli.ExternalProjectName);

            if (externalGit != null && externalProjectName != null)
            {
                string folderName = UtilFramework.FolderName + "ExternalGit/" + externalProjectName + "/" + "Application.Cli";
                UtilCli.DotNet(folderName, "run -- external");
            }
        }
Beispiel #12
0
        /// <summary>
        /// Clone external git repo and call prebuild script.
        /// </summary>
        private static void ExternalGit()
        {
            var configCli = ConfigCli.Load();

            // Clone repo
            var externalGit = UtilFramework.StringNull(configCli.ExternalGit);

            if (externalGit != null)
            {
                string externalFolderName = UtilFramework.FolderName + "ExternalGit/";
                if (!UtilCli.FolderNameExist(externalFolderName))
                {
                    Console.WriteLine("Git Clone ExternalGit");
                    UtilCli.FolderCreate(externalFolderName);
                    UtilCli.Start(externalFolderName, "git", "clone --recursive -q" + " " + externalGit); // --recursive clone also submodule Framework -q do not write to stderr on linux
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Build all layout Websites. For example: "Application.Website/LayoutDefault"
        /// </summary>
        private void BuildWebsite()
        {
            var configCli = ConfigCli.Load();

            // Ensure FolderNameNpmBuild is defined once only in ConfigCli.json.
            ConfigCliWebsite configCliWebsite = configCli.WebsiteList.GroupBy(item => item.FolderNameNpmBuild.ToLower()).Where(group => group.Count() > 1).FirstOrDefault()?.FirstOrDefault();

            UtilFramework.Assert(configCliWebsite == null, string.Format("ConfigCli.json Website defined more than once. Use DomainNameList instead! (FolderNameNpmBuild={0})", configCliWebsite?.FolderNameNpmBuild));

            // Delete folder Application.Server/Framework/Application.Website/
            string folderNameApplicationWebsite = UtilFramework.FolderName + "Application.Server/Framework/Application.Website/";

            UtilCli.FolderDelete(folderNameApplicationWebsite);

            foreach (var website in configCli.WebsiteList)
            {
                Console.WriteLine(string.Format("### Build Website (Begin) - {0}", website.DomainNameListToString()));

                // Delete dist folder
                string folderNameDist = UtilFramework.FolderNameParse(website.FolderNameDist);
                UtilFramework.Assert(folderNameDist != null);
                UtilCli.FolderDelete(folderNameDist);

                // npm run build
                BuildWebsiteNpm(website);
                string folderNameServer = UtilFramework.FolderNameParse(website.FolderNameServerGet(configCli));
                UtilFramework.Assert(folderNameServer != null, "FolderNameServer can not be null!");
                UtilFramework.Assert(folderNameServer.StartsWith("Application.Server/Framework/Application.Website/"), "FolderNameServer has to start with 'Application.Server/Framework/Application.Website/'!");

                // Copy dist folder
                string folderNameSource = UtilFramework.FolderName + folderNameDist;
                string folderNameDest   = UtilFramework.FolderName + folderNameServer;
                if (!UtilCli.FolderNameExist(folderNameSource))
                {
                    throw new Exception(string.Format("Folder does not exist! ({0})", folderNameDest));
                }
                UtilCli.FolderDelete(folderNameDest);
                UtilFramework.Assert(!UtilCli.FolderNameExist(folderNameDest));
                UtilCli.FolderCopy(folderNameSource, folderNameDest, "*.*", true);
                UtilFramework.Assert(UtilCli.FolderNameExist(folderNameDest));

                Console.WriteLine(string.Format("### Build Website (End) - {0}", website.DomainNameListToString()));
            }
        }
Beispiel #14
0
 /// <summary>
 /// Run command line interface.
 /// </summary>
 public void Run(string[] args)
 {
     Title(args);
     try
     {
         ConfigCli.Init(this);
         var configCli = ConfigCli.Load();
         ConfigCli.Save(configCli); // Reset ConfigCli.json
         ConfigCli.CopyConfigCliToConfigServer();
         CommandEnvironment.ConsoleWriteLineCurrentEnvironment(configCli);
         commandLineApplication.Execute(args);
         CopyConfigCliToConfigServer(); // Copy new values from ConfigCli.json to ConfigServer.json
     }
     catch (Exception exception)        // For example unrecognized option
     {
         UtilCli.ConsoleWriteLineError(exception);
         Environment.ExitCode = 1; // echo %errorlevel%
     }
 }
Beispiel #15
0
        protected internal override void Execute()
        {
            ConfigCli configCli = ConfigCli.Load();

            if (optionSilent.OptionGet() == false && configCli.EnvironmentNameGet() != "DEV")
            {
                if (UtilCli.ConsoleReadYesNo(string.Format("Generate CSharp code from {0} database?", configCli.EnvironmentName)) == false)
                {
                    return;
                }
            }

            bool isFrameworkDb = optionFramework.OptionGet();

            if (Script.Run(isFrameworkDb, AppCli))
            {
                UtilCli.ConsoleWriteLineColor("Generate successful!", ConsoleColor.Green);
            }
        }
        protected internal override void Execute()
        {
            ConfigCli configCli          = ConfigCli.Load();
            string    environmentNameOld = configCli.EnvironmentName;

            if (UtilCli.ArgumentValueIsExist(this, argumentName))
            {
                if (UtilCli.ArgumentValue(this, argumentName, out string name))
                {
                    configCli.EnvironmentName = name?.ToUpper();
                }
            }

            configCli.EnvironmentGet(); // Get or init

            if (configCli.EnvironmentName != environmentNameOld)
            {
                ConsoleWriteLineCurrentEnvironment(configCli);
            }

            ConfigCli.Save(configCli);
        }
Beispiel #17
0
        private void ArgumentWebsite()
        {
            ConfigCli configCli = ConfigCli.Load();

            // Input DomainName
            Console.WriteLine("Enter domain name. For example: 'example.com' or empty for default website:");
            Console.Write(">");
            string domainName = Console.ReadLine();

            // Input AppTypeName
            Console.WriteLine("Enter AppTypeName. For example: 'Application.AppMain, Application':");
            Console.Write(">");
            string appTypeName = Console.ReadLine();

            if (Type.GetType(appTypeName) == null)
            {
                UtilCli.ConsoleWriteLineColor(string.Format("Type not found! ({0})", appTypeName), ConsoleColor.Yellow);
            }

            // Input FolderName
            Console.WriteLine("Enter npm build folder name. Or empty if no build. For example: 'Application.Website/LayoutDefault/'. In this folder ci calls npm install; npm build;");
            Console.Write(">");
            string folderNameNpmBuild = Console.ReadLine();

            folderNameNpmBuild = UtilFramework.FolderNameParse(folderNameNpmBuild);

            string folderNameNpmBuildCheck = UtilFramework.FolderName + folderNameNpmBuild;

            if (!Directory.Exists(folderNameNpmBuildCheck))
            {
                UtilCli.ConsoleWriteLineColor(string.Format("Folder does not exist! ({0})", folderNameNpmBuild), ConsoleColor.Yellow);
            }

            // Input FolderNameDist
            Console.WriteLine("Enter dist folder name. For example 'Application.Website/LayoutDefault/dist/'. Content of this folder is copied to FolderNameServer");
            Console.Write(">");
            string folderNameDist = Console.ReadLine();

            folderNameDist = UtilFramework.FolderNameParse(folderNameDist);
            string folderNameDistCheck = UtilFramework.FolderName + folderNameDist;

            if (!Directory.Exists(folderNameDistCheck))
            {
                UtilCli.ConsoleWriteLineColor(string.Format("Folder does not exist! ({0})", folderNameDist), ConsoleColor.Yellow);
            }

            // Add Website
            ConfigCliWebsite website = new ConfigCliWebsite();

            website.DomainNameList = new List <ConfigCliWebsiteDomain>();
            website.DomainNameList.Add(new ConfigCliWebsiteDomain()
            {
                EnvironmentName = configCli.EnvironmentNameGet(), DomainName = domainName, AppTypeName = appTypeName
            });
            website.FolderNameNpmBuild = folderNameNpmBuild;
            website.FolderNameDist     = folderNameDist;

            configCli.WebsiteList.Add(website);

            ConfigCli.Save(configCli);
        }
 public static void ConsoleWriteLineCurrentEnvironment(ConfigCli configCli)
 {
     UtilCli.ConsoleWriteLineColor(string.Format("Current Environment (Name={0})", configCli.EnvironmentNameGet()), ConsoleColor.Green);
 }
Beispiel #19
0
 /// <summary>
 /// Override this method to change default cli configuration.
 /// </summary>
 protected virtual internal void InitConfigCli(ConfigCli configCli)
 {
 }
Beispiel #20
0
        protected internal override void Execute()
        {
            ConfigCli configCli = ConfigCli.Load();

            // Command "json"
            if (UtilCli.ArgumentValueIsExist(this, argumentJson))
            {
                if (UtilCli.ArgumentValue(this, argumentJson, out string json))
                {
                    // Set ConfigCli.json with command: ".\cli.cmd config json='{}'"
                    json = json.Trim('\"');         // Remove quotation marks at the begin and end.
                    json = json.Replace("'", "\""); // To use it in command prompt.
                    // Write
                    try
                    {
                        configCli = UtilFramework.ConfigFromJson <ConfigCli>(json);
                    }
                    catch (Exception exception)
                    {
                        throw new Exception("ConfigCli invalid!", exception);
                    }
                    ConfigCli.Save(configCli);
                }
            }

            // Command "deployAzureGitUrl"
            if (UtilCli.ArgumentValueIsExist(this, argumentDeployAzureGitUrl))
            {
                if (UtilCli.ArgumentValue(this, argumentDeployAzureGitUrl, out string value))
                {
                    // Write
                    configCli.EnvironmentGet().DeployAzureGitUrl = value;
                    ConfigCli.Save(configCli);
                }
                else
                {
                    // Read
                    Console.WriteLine(argumentDeployAzureGitUrl.Name + "=" + configCli.EnvironmentGet().DeployAzureGitUrl);
                }
                return;
            }

            // Command "connectionString"
            if (UtilCli.ArgumentValueIsExist(this, argumentConnectionString))
            {
                ArgumentConnectionString();
                return;
            }

            // Command "connectionStringFramework"
            if (UtilCli.ArgumentValueIsExist(this, argumentConnectionStringFramework))
            {
                ArgumentConnectionStringFramework();
                return;
            }

            // Command "connectionStringApplication"
            if (UtilCli.ArgumentValueIsExist(this, argumentConnectionStringApplication))
            {
                ArgumentConnectionStringApplication();
                return;
            }

            // Command "website"
            if (UtilCli.ArgumentValueIsExist(this, argumentWebsite))
            {
                ArgumentWebsite();
                return;
            }

            // Print ConfigCli.json to screen
            {
                configCli = ConfigCli.Load();
                Console.WriteLine();
                UtilCli.ConsoleWriteLineColor("Add the following environment variable to ci build server: (Value including double quotation marks!)", ConsoleColor.Green);
                string json = UtilFramework.ConfigToJson(configCli, isIndented: false);
                json = json.Replace("\"", "'"); // To use it in command prompt.
                UtilCli.ConsoleWriteLineColor("ConfigCli=", ConsoleColor.DarkGreen);
                UtilCli.ConsoleWriteLineColor(string.Format("\"{0}\"", json), ConsoleColor.DarkGreen);
                Console.WriteLine();
            }
        }
        protected internal override void Execute()
        {
            // Build angular client
            if (!UtilCli.FolderNameExist(UtilFramework.FolderName + "Application.Server/Framework/Framework.Angular/"))
            {
                var commandBuild = new CommandBuild(AppCli);
                UtilCli.OptionSet(ref commandBuild.OptionClientOnly, true);
                commandBuild.Execute();
            }

            if (optionWatch.OptionGet())
            {
                {
                    ConfigCli configCli = ConfigCli.Load();

                    Console.WriteLine("Select Website:");

                    for (int i = 0; i < configCli.WebsiteList.Count; i++)
                    {
                        Console.WriteLine(string.Format("{0}={1}", i + 1, configCli.WebsiteList[i].FolderNameNpmBuild));
                    }

                    Console.Write("Website: ");

                    var websiteIndex = int.Parse(Console.ReadLine()) - 1;

                    var website = configCli.WebsiteList[websiteIndex];

                    string folderNameNpmBuilt = UtilFramework.FolderName + website.FolderNameNpmBuild;
                    string folderNameDist     = UtilFramework.FolderName + website.FolderNameDist;

                    string folderNameAngular         = UtilFramework.FolderName + "Framework/Framework.Angular/application/";
                    string folderNameCustomComponent = UtilFramework.FolderName + "Application.Website/Shared/CustomComponent/";

                    Console.WriteLine("Copy folder dist/");
                    UtilCli.FolderCopy(folderNameDist, folderNameAngular + "src/Application.Website/dist/", "*.*", true);

                    Console.WriteLine("Copy folder CustomComponent/");
                    UtilCli.FolderCopy(folderNameCustomComponent, folderNameAngular + "src/Application.Website/Shared/CustomComponent/", "*.*", true);

                    bool isWebsiteWatch = UtilCli.ConsoleReadYesNo("Start Website npm watch?");
                    bool isFileSync     = UtilCli.ConsoleReadYesNo("Start Website FileSync (dist/ to Angular)?");
                    bool isAngular      = UtilCli.ConsoleReadYesNo("Start Angular?");
                    bool isServer       = UtilCli.ConsoleReadYesNo("Start Server?");

                    // FileSync
                    if (isFileSync)
                    {
                        FileSync fileSync = new FileSync();
                        fileSync.AddFolder(folderNameDist, folderNameAngular + "src/Application.Website/dist/");
                        fileSync.AddFolder(folderNameAngular + "src/Application.Website/Shared/CustomComponent/", folderNameCustomComponent);
                    }

                    // Website --watch
                    if (isWebsiteWatch)
                    {
                        UtilCli.Npm(folderNameNpmBuilt, "run build -- --watch", isWait: false);
                    }

                    // Angular client
                    if (isAngular)
                    {
                        UtilCli.Npm(folderNameAngular, "start -- --disable-host-check", isWait: false); // disable-host-check to allow for example http://localhost2:4200/
                    }

                    // .NET Server
                    if (isServer)
                    {
                        string folderName = UtilFramework.FolderName + @"Application.Server/";
                        UtilCli.DotNet(folderName, "run", isWait: false);
                    }

                    void heartBeat()
                    {
                        Console.WriteLine();
                        Console.WriteLine(UtilFramework.DateTimeToString(DateTime.Now));
                        if (isAngular)
                        {
                            UtilCli.ConsoleWriteLineColor("Angular: http://" + website.DomainNameList.First().DomainName + ":4200/", System.ConsoleColor.Green);
                        }
                        if (isServer)
                        {
                            UtilCli.ConsoleWriteLineColor("Server: http://" + website.DomainNameList.First().DomainName + ":50919/", System.ConsoleColor.Green);
                        }
                        if (isFileSync)
                        {
                            UtilCli.ConsoleWriteLineColor("Modify Website: " + folderNameNpmBuilt, System.ConsoleColor.Green);
                            UtilCli.ConsoleWriteLineColor("Modify CustomComponent: " + folderNameCustomComponent, System.ConsoleColor.Green);
                        }
                        if (isAngular)
                        {
                            UtilCli.ConsoleWriteLineColor("Modify Angular: " + folderNameAngular, System.ConsoleColor.Green);
                        }
                        Task.Delay(5000).ContinueWith((Task task) => heartBeat());
                    }

                    if (isFileSync || isWebsiteWatch || isAngular || isServer)
                    {
                        heartBeat();
                        while (true)
                        {
                            Console.ReadLine(); // Program would end and with it FileSync
                        }
                    }
                }
            }
            else
            {
                string folderName = UtilFramework.FolderName + @"Application.Server/";
                UtilCli.VersionBuild(() =>
                {
                    UtilCli.DotNet(folderName, "build");
                });
                UtilCli.DotNet(folderName, "run --no-build", false);
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    UtilCli.OpenWebBrowser("http://localhost:50919/"); // For port setting see also: Application.Server\Properties\launchSettings.json (applicationUrl, sslPort)
                }
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    // Ubuntu list all running processes: 'ps'
                    // To reboot Ubuntu type on Windows command prompt: 'wsl -t Ubuntu-18.04'
                    // Ubuntu show processes tool: 'htop'
                    UtilCli.ConsoleWriteLineColor("Stop server with command 'killall -SIGKILL Application.Server node dotnet'", System.ConsoleColor.Yellow);
                }
            }
        }