public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter store my shopify domain (exact URL): "); var store = Console.ReadLine(); xc.AskForInput(this, "Enter plan id: "); var planId = Int32.Parse(Console.ReadLine()); AspNetUser user = null; Plan plan = null; using (var scope = xc.WebHost.Services.CreateScope()) { var userService = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); user = userService.FindSingleWhere(x => x.MyShopifyDomain == store); if (user == null) { xc.WriteError(this, "Store not found."); } else { var planService = scope.ServiceProvider.GetService <IDbService <Plan> >(); plan = planService.FindSingleWhere(x => x.Id == planId); if (plan == null) { xc.WriteError(this, "Plan not found."); } else { xc.WriteSuccess(this, $"Found the plan {plan.Name}."); var prevPlanId = user.PlanId; user.PlanId = plan.Id; xc.WriteInfo(this, "Updating plan id for the store."); var updatedUser = userService.Update(user, user.Id); if (updatedUser == null) { xc.WriteError(this, "Update failed."); } else { xc.WriteSuccess(this, "Successfully updated."); var table = xc.CreateTable(new string[] { "Column", "Value" }); table.AddRow(new[] { "Id", updatedUser.Id }); table.AddRow(new[] { "Store", updatedUser.MyShopifyDomain }); table.AddRow(new[] { "PreviousPlan", prevPlanId.Value.ToString() }); table.AddRow(new[] { "PreviousPlan", updatedUser.PlanId.ToString() }); xc.WriteTable(table); } } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter myshopify domain(exact url): "); using (var scope = xc.WebHost.Services.CreateScope()) { string input = Console.ReadLine(); UserManager <AspNetUser> db = scope.ServiceProvider.GetService <UserManager <AspNetUser> >(); var user = db.FindByNameAsync(input).Result; if (user != null) { xc.WriteSuccess(this, "Found store."); xc.AskForInput(this, "Make this store admin ? (y or n): "); var confirm = Console.ReadLine(); if (confirm == "y" || confirm == "Y") { if (db.IsInRoleAsync(user, UserInContextHelper.ADMIN_ROLE).Result) { xc.WriteWarning(this, $"Account ({user.MyShopifyDomain}) is already an admin account."); } else { xc.WriteInfo(this, "Updating store as admin account."); var result = await db.AddToRoleAsync(user, UserInContextHelper.ADMIN_ROLE); if (result.Succeeded) { xc.WriteSuccess(this, $"Successfully updated."); } else { xc.WriteError(this, $"Update failed."); } } } else { xc.WriteWarning(this, $"Did not update the store as admin."); } } else { xc.WriteWarning(this, "Store not found."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { xc.AskForInput(this, "Enter TO email address: "); var to = Console.ReadLine(); if (IsValidEmail(to)) { xc.AskForInput(this, "Enter FROM email address: "); var from = Console.ReadLine(); if (IsValidEmail(from)) { xc.AskForInput(this, "Enter subject: "); var subject = Console.ReadLine(); xc.AskForInput(this, "Enter message: "); var message = Console.ReadLine(); var emailer = scope.ServiceProvider.GetService <IEmailer>(); emailer.AddTo(to); emailer.SetFromAddress(from); emailer.SetSubject(subject); emailer.SetMessage(message, true); var result = await emailer.Send(true); if (result) { xc.WriteSuccess(this, $"Successfully sent the email to {to}."); } else { xc.WriteError(this, $"Could not send the email to {to}."); } } else { xc.WriteWarning(this, "FROM email address is not valid."); } } else { xc.WriteWarning(this, "TO email address is not valid."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter command name: "); using (var scope = xc.WebHost.Services.CreateScope()) { string command = Console.ReadLine(); var commandClass = xc.FindCommand(command); if (commandClass != null) { try { var commandInstance = xc.CreateCommandInstance(commandClass); xc.WriteHelp(commandInstance); } catch (Exception) { xc.WriteError(this, $"Unable to display help for {command}"); } } else { xc.WriteWarning(this, "Command not found."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter myshopify domain: "); using (var scope = xc.WebHost.Services.CreateScope()) { string input = Console.ReadLine(); var db = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); var user = db.FindSingleWhere(x => x.MyShopifyDomain == input); if (user != null) { xc.WriteSuccess(this, "Found the store."); var passGen = scope.ServiceProvider.GetService <IGenerateUserPassword>(); var pass = passGen.GetPassword(new Data.Domain.AppModels.PasswordGeneratorInfo(user)); var table = xc.CreateTable(new[] { "UserName", "Password" }); table.AddRow(user.UserName, pass); xc.WriteTable(table); } else { xc.WriteWarning(this, "Store not found."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { xc.AskForInput(this, "Enter setting name or id: "); var sIdName = Console.ReadLine(); var settingsService = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); var setting = settingsService.FindSingleWhere(x => x.SettingName == sIdName || x.Id.ToString() == sIdName); if (setting == null) { xc.WriteError(this, "Setting not found."); } else { xc.WriteSuccess(this, $"Found the setting '{setting.SettingName}'."); xc.AskForInput(this, "Enter setting value: "); var sVal = Console.ReadLine(); var oldValue = setting.Value; setting.Value = sVal; xc.WriteInfo(this, "Updating the setting."); setting = settingsService.Update(setting, setting.Id); if (setting == null) { xc.WriteWarning(this, "Update failed."); } else { xc.WriteSuccess(this, "Successfully updated."); var table = xc.CreateTable(new[] { "Column", "Value" }); table.AddRow("SettingId", setting.Id); table.AddRow("SettingName", setting.SettingName); table.AddRow("OldValue", oldValue); table.AddRow("UpdatedValue", setting.Value); xc.WriteTable(table); } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter myshopify domain (exact url): "); using (var scope = xc.WebHost.Services.CreateScope()) { string input = Console.ReadLine(); var db = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); var user = db.FindSingleWhere(x => x.MyShopifyDomain == input); if (user != null) { xc.AskForInput(this, "Enter shopify token: "); var token = Console.ReadLine(); var previousToken = user.ShopifyAccessToken; user.ShopifyAccessToken = token; xc.WriteInfo(this, "Updating token."); var updatedUser = db.Update(user, user.Id); if (updatedUser != null) { xc.WriteSuccess(this, "Successfully saved new token for the store."); var table = xc.CreateTable(new string[] { "Column", "Value" }); table.AddRow(new[] { "Id", updatedUser.Id }); table.AddRow(new[] { "Store", updatedUser.MyShopifyDomain }); table.AddRow(new[] { "PreviousToken", previousToken }); table.AddRow(new[] { "CurrentToken", updatedUser.ShopifyAccessToken }); xc.WriteTable(table); } else { xc.WriteError(this, "Error saving new token for the store."); } } else { xc.WriteWarning(this, "Store not found."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter store ID or my shopify domain: "); var storeId = Console.ReadLine(); AspNetUser store = null; using (var scope = xc.WebHost.Services.CreateScope()) { var userService = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); store = userService.FindSingleWhere(x => x.Id == storeId || x.MyShopifyDomain == storeId); if (store == null) { xc.WriteWarning(this, "Store not found."); } else { if (!store.ShopifyChargeId.HasValue) { xc.WriteWarning(this, "Store is not connected to shopify billing yet."); } else if (string.IsNullOrEmpty(store.ShopifyAccessToken)) { xc.WriteWarning(this, "Store is not connected to shopify API yet.No access token."); } else { var shopifyApi = scope.ServiceProvider.GetService <IShopifyApi>(); var rObj = await shopifyApi.GetRecurringChargeAsync(store.MyShopifyDomain, store.ShopifyAccessToken, store.ShopifyChargeId.Value); xc.WriteSuccess(this, $"Found charge/billing infromation for {store.MyShopifyDomain}."); var table = xc.CreateTable(new string[] { "Name", "Value" }); table.AddRow(new[] { "Id", rObj.Id.Value.ToString() }); table.AddRow(new[] { "Status", rObj.Status }); table.AddRow(new[] { "Name", rObj.Name }); table.AddRow(new[] { "Price", rObj.Price.Value.ToString("C") }); table.AddRow(new[] { "Is Test", rObj.Test.ToString() }); table.AddRow(new[] { "Trial Ends/Ended On", rObj.TrialEndsOn?.DateTime.ToString("F") }); table.AddRow(new[] { "Trial Days", rObj.TrialDays.ToString() }); xc.WriteTable(table); } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter exatct or part of my shopify url or email: "); using (var scope = xc.WebHost.Services.CreateScope()) { string input = Console.ReadLine(); if (string.IsNullOrEmpty(input)) { xc.WriteWarning(this, "Invalid url or email."); } else { var userService = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); var users = userService.FindManyWhere(x => x.MyShopifyDomain.Contains(input) || x.Email.Contains(input)); if (users.Count <= 0) { xc.WriteWarning(this, "Nothing found."); } else { xc.WriteSuccess(this, $"Found {users.Count} store(s)."); var table = xc.CreateTable(new[] { "Id", "MyShopifyUrl", "Email", "Plan", "ChargeId", "Token", "BillingOn", "IsAdmin" }); UserManager <AspNetUser> _userManager = scope.ServiceProvider.GetService <UserManager <AspNetUser> >(); var planService = scope.ServiceProvider.GetService <IDbService <Plan> >(); foreach (var u in users) { var isAdmin = await _userManager.IsInRoleAsync(u, UserInContextHelper.ADMIN_ROLE); var plan = planService.FindSingleWhere(x => x.Id == u.PlanId); string planInfo = plan == null ? "n/a" : plan.Name; table.AddRow(u.Id, u.MyShopifyDomain, u.Email, $"{u.PlanId}({planInfo})", u.ShopifyChargeId, u.ShopifyAccessToken, u.BillingOn?.Date.ToShortDateString(), isAdmin); } xc.WriteTable(table); } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { var config = scope.ServiceProvider.GetService <IConfiguration>(); var settingDB = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); var remoteSite = settingDB.FindSingleWhere(x => x.SettingName == CORE_SYSTEM_SETTING_NAMES.APP_BASE_URL.ToString()); if (remoteSite == null && string.IsNullOrEmpty(remoteSite.Value)) { xc.WriteError(this, "App base url is not found in the db.Cannot continue."); } else { xc.AskForInput(this, "Enter log level (case sensitive) you want to switch over: "); var level = Console.ReadLine(); xc.WriteInfo(this, $"Sending request to {remoteSite.Value} to switch log level to {level}."); var data = new WebClient().DownloadString($"{remoteSite.Value}/{XConsole.SERVICE_CONSTROLLER}/ChangeLogLevel?tolevel={level}&{config[AdminPasswordVerification.ADMIN_PASS_KEYT]}={config[AdminPasswordVerification.ADMIN_PASS_VALUE]}"); xc.WriteSuccess(this, "Received response."); try { xc.WriteInfo(this, "Now trying to parse received data.."); var response = JsonConvert.DeserializeObject <bool>(data); if (response) { xc.WriteSuccess(this, "Server responded switching was successful."); } else { xc.WriteError(this, "Server responded switching was unsuccessful."); } } catch (Exception ex) { xc.WriteError(this, "Error parsing received data." + ex.Message); } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { var db = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); xc.AskForInput(this, "Enter the myshopify domain of the target shopify store: "); var storeUrl = Console.ReadLine(); if (string.IsNullOrEmpty(storeUrl)) { xc.WriteError(this, "Not a valid my shopify domain name."); } else if (!storeUrl.EndsWith(".myshopify.com")) { xc.WriteError(this, "Not a valid my shopify domain name."); } else { var apiKey = db.FindSingleWhere(x => x.SettingName == CORE_SYSTEM_SETTING_NAMES.API_KEY.ToString()); if (apiKey == null) { xc.WriteError(this, $"Setting { CORE_SYSTEM_SETTING_NAMES.API_KEY.ToString()} is missing in the settings table."); } else { if (string.IsNullOrEmpty(apiKey.Value)) { xc.WriteWarning(this, $"{CORE_SYSTEM_SETTING_NAMES.API_KEY.ToString()} setting doesn't have a value. Please update that setting first."); } else /*all good */ { xc.WriteInfo(this, "The installation URL for the app is "); xc.WriteSuccess(this, $"{storeUrl}/admin/api/auth?api_key={apiKey.Value}"); } } } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { xc.AskForInput(this, "Enter log level (case sensitive) you want to switch over: "); var toLevel = Console.ReadLine(); xc.WriteInfo(this, $"Trying to change log level to {toLevel} ..."); Serilog.Events.LogEventLevel level = (Serilog.Events.LogEventLevel)Enum.Parse(typeof(Serilog.Events.LogEventLevel), toLevel); Extensions.HostBuilderExtensions.SwitchToLogLevel(level); xc.WriteSuccess(this, "Done"); } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Filter by (leave blank for all): ", false); var filter = Console.ReadLine(); List <string> list; if (string.IsNullOrEmpty(filter)) { list = xc.CommandList; } else { filter = filter.Replace("-", "").ToLower(); list = xc.CommandList.Where(x => x.ToLower().Contains(filter)).ToList(); } xc.WriteInfo(this, $"Total {list.Count} commands found."); if (list.Count > 0) { var table = xc.CreateTable(new string[] { "Command", "Description" }); foreach (string className in list) { try { var instance = xc.CreateCommandInstance(className); table.AddRow(new[] { instance.GetName(), instance.GetDescription() }); } catch (Exception) { throw; } } //table.Write(ConsoleTables.Format.Alternative); xc.WriteTable(table); } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Filter by name (or part of it) or leave blank for all settings: "); using (var scope = xc.WebHost.Services.CreateScope()) { string input = Console.ReadLine(); var settingsService = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); List <SystemSetting> setting; xc.WriteInfo(this, "Searching settings."); if (string.IsNullOrEmpty(input)) { setting = settingsService.FindAll(); } else { setting = settingsService.FindManyWhere(x => x.SettingName.Contains(input)); } if (setting.Count <= 0) { xc.WriteWarning(this, "Total 0 settings found."); } else { xc.WriteSuccess(this, $"Total {setting.Count} setting(s) found."); var table = xc.CreateTable(new[] { "ID", "Name", "DisplayName", "Group", "Value" }); foreach (var s in setting) { table.AddRow(s.Id, s.SettingName, s.DisplayName, s.GroupName, s.Value); } xc.WriteTable(table); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Filter by name or ID (leave blank for all): ", false); var filter = Console.ReadLine(); using (var scope = xc.WebHost.Services.CreateScope()) { var db = scope.ServiceProvider.GetService <IDbService <Plan> >(); List <Plan> list; if (string.IsNullOrEmpty(filter)) { list = db.FindAll(); } else { list = db.FindManyWhere(x => x.Name.Contains(filter) || x.Id.ToString() == filter); } xc.WriteInfo(this, "Listing plans."); if (list.Count > 0) { xc.WriteSuccess(this, $"Total {list.Count} plan(s) found."); var table = xc.CreateTable(new string[] { "Id", "Name", "TrialDays", "IsActive", "IsDev", "IsTest", "DisplayOrder", "IsPopular", "Price" }); foreach (var i in list) { table.AddRow(i.Id, i.Name, i.TrialDays, i.Active, i.IsDev, i.IsTest, i.DisplayOrder, i.IsPopular, i.Price.ToString("C")); } xc.WriteTable(table); } else { xc.WriteWarning(this, "Total 0 plan(s) found."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { xc.AskForInput(this, "Enter file name with or without path (file extension not needed): "); var fileName = Console.ReadLine(); if (!string.IsNullOrEmpty(fileName) && !string.IsNullOrWhiteSpace(fileName)) { using (var scope = xc.WebHost.Services.CreateScope()) { var userService = scope.ServiceProvider.GetService <IDbService <AspNetUser> >(); var users = userService.FindAll(); xc.WriteInfo(this, $"Found {users.Count} records"); var csv = new StringBuilder(); csv.AppendLine("Email Address,First Name"); foreach (var u in users) { var newLine = string.Format("{0},{1}", u.Email, u.MyShopifyDomain); csv.AppendLine(newLine); } await File.WriteAllTextAsync(fileName + ".csv", csv.ToString()); xc.WriteInfo(this, $"Finished writing to {new FileInfo(fileName).FullName}.csv file."); xc.WriteSuccess(this, $"Export was successfull."); } } else { xc.WriteWarning(this, "Invalid file name."); } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { var ipServiceUrl = "http://ipinfo.io/ip"; string externalIp = null; try { externalIp = new WebClient().DownloadString(ipServiceUrl); externalIp = Regex.Replace(externalIp, @"\r\n?|\n|\t", String.Empty); xc.WriteInfo(this, $"(FYI : your external IP is - {externalIp})"); } catch (Exception) { xc.WriteInfo(this, $"(FYI : your external IP is - ", false); xc.WriteError(this, $"failed to retrive using {ipServiceUrl}.)"); } xc.AskForInput(this, "Enter the IP you want to add to the Privilege IP list: "); string ip = Console.ReadLine(); if (!string.IsNullOrEmpty(ip)) { var db = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); var item = db.FindSingleWhere(x => x.SettingName == CORE_SYSTEM_SETTING_NAMES.PRIVILEGED_IPS.ToString()); if (item == null) { xc.WriteError(this, $"Could not add IP because the setting {CORE_SYSTEM_SETTING_NAMES.PRIVILEGED_IPS} doesn't exit in the database."); } else { var alreadyExists = false; if (item.Value != null) { if (item.Value.Contains(ip)) { xc.WriteInfo(this, $"IP {ip} is already in the privileged IP list."); alreadyExists = true; } } if (!alreadyExists) { ip = ip.Trim(); item.Value = string.IsNullOrEmpty(item.Value) ? ip : $"{item.Value},{ip}"; xc.WriteInfo(this, "Updating IP list."); var itemUpdated = db.Update(item, item.Id); if (itemUpdated == null) { xc.WriteError(this, text: $"Adding {externalIp} to the privileged IP list failed."); } else { xc.WriteSuccess(this, $"{externalIp} has been added to the privileged IP list."); } } } } else { xc.WriteWarning(this, $"Nothing has been added to the privileged IP list."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { AspNetUser user = new AspNetUser(); xc.AskForInput(this, "Enter myshopify URL (without http part): "); user.MyShopifyDomain = Console.ReadLine(); xc.AskForInput(this, "Enter shop email: "); user.Email = Console.ReadLine(); xc.AskForInput(this, "Enter plan id: "); var pid = Console.ReadLine(); user.PlanId = Int32.Parse(pid); xc.AskForInput(this, "Enter shopify access token: "); user.ShopifyAccessToken = Console.ReadLine(); user.UserName = user.MyShopifyDomain; xc.AskForInput(this, "Enter Charge Id (optoinal for admin store): "); var cid = Console.ReadLine(); if (string.IsNullOrEmpty(cid)) { user.ShopifyChargeId = null; } else { user.ShopifyChargeId = long.Parse(cid); } user.BillingOn = DateTime.Now; UserManager <AspNetUser> db = scope.ServiceProvider.GetService <UserManager <AspNetUser> >(); xc.WriteInfo(this, "Installing the app for the store."); var passGen = scope.ServiceProvider.GetService <IGenerateUserPassword>(); var pass = passGen.GetPassword(new Data.Domain.AppModels.PasswordGeneratorInfo(user)); var result = await db.CreateAsync(user, pass); if (result.Succeeded) { xc.WriteSuccess(this, "Successfull installed the app."); var table = xc.CreateTable(new string[] { "Column", "Value" }); table.AddRow("Id", user.Id); table.AddRow("UserName", user.UserName); table.AddRow("MyShopifyDomain", user.MyShopifyDomain); table.AddRow("Email", user.Email); table.AddRow("ShopifyAccessToken", user.ShopifyAccessToken); table.AddRow("PlanId", user.PlanId); table.AddRow("ShopifyChargeId", user.ShopifyChargeId); table.AddRow("BilingOn", user.BillingOn); xc.WriteTable(table); } else { xc.WriteError(this, $"Installation error occurred.{Environment.NewLine}{result.ToString()}"); } } } catch (Exception ex) { xc.WriteException(this, ex); } }
public async Task Run(XConsole xc) { try { using (var scope = xc.WebHost.Services.CreateScope()) { xc.AskForInput(this, "Enter the IP you want to remove from the privilege IP list: "); string ip = Console.ReadLine(); if (!string.IsNullOrEmpty(ip)) { var db = scope.ServiceProvider.GetService <IDbService <SystemSetting> >(); var item = db.FindSingleWhere(x => x.SettingName == CORE_SYSTEM_SETTING_NAMES.PRIVILEGED_IPS.ToString()); if (item == null) { xc.WriteError(this, $"Could not add IP because the setting {CORE_SYSTEM_SETTING_NAMES.PRIVILEGED_IPS} doesn't exit in the database."); } else { if (item.Value != null) { if (item.Value.Contains(ip)) { xc.WriteInfo(this, $"IP {ip} is found in the privileged IP list."); List <string> _ips = new List <string>(); xc.WriteInfo(this, $"Updating privileged IP table."); foreach (var i in item.Value.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) { if (!i.Trim().Equals(ip.Trim())) { _ips.Add(i); } } item.Value = string.Join(',', _ips); var itemUpdated = db.Update(item, item.Id); if (itemUpdated == null) { xc.WriteError(this, text: $"Removing {ip} to the privileged IP list failed."); } else { xc.WriteSuccess(this, $"{ip} has been removed from the privileged IP list."); } } else { xc.WriteWarning(this, $"The ip {ip} doesn't even exist in the priviledged IP tables."); } } } } else { xc.WriteWarning(this, $"Nothing has been removed from the privileged IP list."); } } } catch (Exception ex) { xc.WriteException(this, ex); } }