public SilentUpgradeComponent(IRuntimeState runtimeState, IGlobalSettings settings, IProfilingLogger logger, IUmbracoDatabaseFactory databaseFactory, DatabaseBuilder databaseBuilder) { this.runtimeState = runtimeState; this.globalSettings = settings; this.logger = logger; this.databaseFactory = databaseFactory; this.databaseBuilder = databaseBuilder; // Check to see if Silent Upgrade is on in web.config // <add key="SilientUpgrade" value="true" /> var silentUpgrade = ConfigurationManager.AppSettings["SilentUpgrade"].TryConvertTo <bool>(); if (silentUpgrade.Success && silentUpgrade.Result) { logger.Info <SilentUpgradeComposer>("SilentUpgrade is On"); SilentUpgradeOn = true; // we only need to worry about the request when we are on. UmbracoModule.EndRequest += UmbracoModule_EndRequest; } else { logger.Info <SilentUpgradeComposer>("SilentUpgrade is Off"); } }
public override bool PerformRun() { if (!AppSettings.CandidContribs.GuestbookGitHubApi.Enabled) { _logger.Info <GuestbookGitHub>("GuestbookGitHubApi import disabled"); return(false); } if (string.IsNullOrWhiteSpace(AppSettings.CandidContribs.GuestbookGitHubApi.CurrentEvent)) { _logger.Info <GuestbookGitHub>("GuestbookGitHubApi import aborted: no current event set"); return(false); } _logger.Info <GuestbookGitHub>("GuestbookGitHubApi import started"); if (!string.IsNullOrWhiteSpace(AppSettings.CandidContribs.GuestbookGitHubApi.AccessToken)) { _guestbookGitHubService.DownloadGuestbookFiles(AppSettings.CandidContribs.GuestbookGitHubApi.CurrentEvent); } _guestbookGitHubService.PersistAsJson(AppSettings.CandidContribs.GuestbookGitHubApi.CurrentEvent); _logger.Info <GuestbookGitHub>("GuestbookGitHubApi import finished"); return(true); }
/// <summary> /// Report the changes for a folder /// </summary> /// <param name="folder">Folder to run the report for</param> /// <param name="handlers">List of SyncHandlers to use for the report</param> /// <param name="callbacks">Callback functions to keep UI uptodate</param> /// <returns>List of actions detailing what would and wouldn't change</returns> public IEnumerable <uSyncAction> Report(string folder, IEnumerable <ExtendedHandlerConfigPair> handlers, uSyncCallbacks callbacks) { var sw = Stopwatch.StartNew(); fireBulkStarting(ReportStarting); logger.Debug <uSyncService>("Reporting For [{0}]", string.Join(",", handlers.Select(x => x.Handler.Name))); var actions = new List <uSyncAction>(); var summary = new SyncProgressSummary(handlers.Select(x => x.Handler), "Reporting", handlers.Count()); if (GlobalSettings.DebugMode && settings.ReportDebug) { // debug - full export into a dated folder. summary.UpdateMessage("Debug: Creating Extract in Tracker folder"); logger.Warn <uSyncService>("Running Report Debug - this can be a slow process, don't enable unless you need it"); callbacks?.Callback?.Invoke(summary); this.Export($"~/uSync/Tracker/{DateTime.Now.ToString("yyyyMMdd_HHmmss")}/", handlers, callbacks); } foreach (var configuredHandler in handlers) { var handler = configuredHandler.Handler; var handlerSettings = configuredHandler.Settings; summary.Increment(); summary.UpdateHandler(handler.Name, HandlerStatus.Processing, $"Reporting {handler.Name}", 0); callbacks?.Callback?.Invoke(summary); var handlerActions = handler.Report($"{folder}/{handler.DefaultFolder}", handlerSettings, callbacks?.Update); actions.AddRange(handlerActions); summary.UpdateHandler(handler.Name, HandlerStatus.Complete, handlerActions.CountChanges(), handlerActions.ContainsErrors()); } summary.UpdateMessage("Report Complete"); callbacks?.Callback?.Invoke(summary); fireBulkComplete(ReportComplete, actions); sw.Stop(); logger.Info <uSyncService>("uSync Report: {handlerCount} handlers, processed {itemCount} items, {changeCount} changes in {ElapsedMilliseconds}ms", handlers.Count(), actions.Count, actions.CountChanges(), sw.ElapsedMilliseconds); callbacks?.Update?.Invoke($"Processed {actions.Count} items in {sw.ElapsedMilliseconds}ms", 1, 1); return(actions); }
public override bool PerformRun() { // Globally disabled by feature flag if (!_settings.EnableCleanup) { _logger.Info <ContentVersionCleanup>("ContentVersionCleanup task will not run as it has been globally disabled via configuration."); return(false); } if (_runtimeState.Level != RuntimeLevel.Run) { return(true); // repeat... } switch (_runtimeState.ServerRole) { case ServerRole.Replica: _logger.Debug <ContentVersionCleanup>("Does not run on replica servers."); return(true); // DO repeat, server role can change case ServerRole.Unknown: _logger.Debug <ContentVersionCleanup>("Does not run on servers with unknown role."); return(true); // DO repeat, server role can change case ServerRole.Single: case ServerRole.Master: default: break; } // Ensure we do not run if not main domain, but do NOT lock it if (!_runtimeState.IsMainDom) { _logger.Debug <ContentVersionCleanup>("Does not run if not MainDom."); return(false); // do NOT repeat, going down } var count = _service.PerformContentVersionCleanup(DateTime.Now).Count; if (count > 0) { _logger.Info <ContentVersionCleanup>("Deleted {count} ContentVersion(s).", count); } else { _logger.Debug <ContentVersionCleanup>("Task complete, no items were Deleted."); } return(true); }
/// <summary> /// add the given section to the given user group /// </summary> /// <remarks> /// if umbraco throws an exception here, we capture it /// because if we don't umbraco won't startup and that /// might be a bad thing :( /// </remarks> /// <param name="groupAlias"></param> /// <param name="sectionAlias"></param> private void AddSection(string groupAlias, string sectionAlias) { using (logger.DebugDuration <CustomSectionComponent>($"Adding Section {sectionAlias} to {groupAlias}")) { var group = userService.GetUserGroupByAlias(groupAlias); if (group != null) { if (!group.AllowedSections.Contains(sectionAlias)) { group.AddAllowedSection(sectionAlias); try { userService.Save(group); logger.Info <CustomSectionComponent>($"Section {sectionAlias} added to {groupAlias} group"); } catch (Exception ex) { logger.Warn <CustomSectionComponent>("Error adding section {0} to group {1} [{2}]", sectionAlias, groupAlias, ex.Message); } } } } }
private void WatcherOnChanged(object sender, FileSystemEventArgs args) { var changed = args.Name; // don't reset when our files change because we are building! // // comment it out, and always ignore our files, because it seems that some // race conditions can occur on slow Cloud filesystems and then we keep // rebuilding //if (_building && OurFiles.Contains(changed)) //{ // //_logger.Info<PureLiveModelFactory>("Ignoring files self-changes."); // return; //} // always ignore our own file changes if (OurFiles.Contains(changed)) { return; } _logger.Info <PureLiveModelFactory>("Detected files changes."); lock (SyncRoot) // don't reset while being locked ResetModels(); }
private async Task ProcessTasksAsync(CancellationToken token) { var scheduledTasks = _settings.ScheduledTasks.Tasks; foreach (var t in scheduledTasks) { var runTask = false; if (ScheduledTaskTimes.ContainsKey(t.Alias) == false) { runTask = true; ScheduledTaskTimes.Add(t.Alias, DateTime.Now); } // Add 1 second to timespan to compensate for differencies in timer else if ( new TimeSpan( DateTime.Now.Ticks - ((DateTime)ScheduledTaskTimes[t.Alias]).Ticks).TotalSeconds + 1 >= t.Interval) { runTask = true; ScheduledTaskTimes[t.Alias] = DateTime.Now; } if (runTask) { var taskResult = await GetTaskByHttpAync(t.Url, token); if (t.Log) { _logger.Info <ScheduledTasks>("{TaskAlias} has been called with response: {TaskResult}", t.Alias, taskResult); } } } }
//ToDo: Refactor after reimplement CacheRefresher events public void Initialize() { foreach (var index in _indexCreator.Create()) { _examineManager.AddIndex(index); ElasticSearchIndex luceneIndex = (ElasticSearchIndex)index; } _logger.Debug <ExamineComponent>("Examine shutdown registered with MainDom"); var registeredIndexers = _examineManager.Indexes.OfType <IIndex>().Count(); _logger.Info <ExamineComponent>("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers); // don't bind event handlers if we're not suppose to listen if (registeredIndexers == 0) { return; } ContentCacheRefresher.CacheUpdated += ContentCacheRefresherUpdated; ContentTypeCacheRefresher.CacheUpdated += ContentTypeCacheRefresherUpdated; MediaCacheRefresher.CacheUpdated += MediaCacheRefresherUpdated; MemberCacheRefresher.CacheUpdated += MemberCacheRefresherUpdated; }
private IEnumerable <Type> PrepareComposerTypes() { // create a list, remove those that cannot be enabled due to runtime level var composerTypeList = _composerTypes .Where(x => { // use the min/max levels specified by the attribute if any // otherwise, min: user composers are Run, anything else is Unknown (always run) // max: everything is Run (always run) var attr = x.GetCustomAttribute <RuntimeLevelAttribute>(); var minLevel = attr?.MinLevel ?? (x.Implements <IUserComposer>() ? RuntimeLevel.Run : RuntimeLevel.Unknown); var maxLevel = attr?.MaxLevel ?? RuntimeLevel.Run; return(_composition.RuntimeState.Level >= minLevel && _composition.RuntimeState.Level <= maxLevel); }) .ToList(); // enable or disable composers EnableDisableComposers(composerTypeList); // sort the composers according to their dependencies var requirements = new Dictionary <Type, List <Type> >(); foreach (var type in composerTypeList) { requirements[type] = null; } foreach (var type in composerTypeList) { GatherRequirementsFromRequireAttribute(type, composerTypeList, requirements); GatherRequirementsFromRequiredByAttribute(type, composerTypeList, requirements); } // only for debugging, this is verbose //_logger.Debug<Composers>(GetComposersReport(requirements)); // sort composers var graph = new TopoGraph <Type, KeyValuePair <Type, List <Type> > >(kvp => kvp.Key, kvp => kvp.Value); graph.AddItems(requirements); List <Type> sortedComposerTypes; try { sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).ToList(); } catch (Exception e) { // in case of an error, force-dump everything to log _logger.Info <Composers>("Composer Report:\r\n{ComposerReport}", GetComposersReport(requirements)); _logger.Error <Composers>(e, "Failed to sort composers."); throw; } // bit verbose but should help for troubleshooting //var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine; _logger.Debug <Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes); return(sortedComposerTypes); }
public void Initialize() { // double check - is this on in config // are we in upgrade mode (we should be - we only register in upgrade) if (!SilentUpgradeOn || runtimeState.Level != RuntimeLevel.Upgrade) { return; } // Do we need to lock? the upgrade so it only happens once? logger.Debug <SilentUpgradeComponent>("Silently upgrading the Site"); // The 'current' steps for upgrading Umbraco try { // // If these steps change in the core then this will be wrong. // // We don't run the file permission step, we assume you have that sorted already. // and besides its internal and we can't get to the tests // FilePermissionHelper.RunFilePermissionTestSuite(out result); // Step: 'DatabaseInstallStep' var result = databaseBuilder.CreateSchemaAndData(); if (!result.Success) { // failed. throw new Exception("Upgrade Failed - Create Schema"); } // Step: 'DatabaseUpgradeStep' var plan = new UmbracoPlan(); logger.Debug <SilentUpgradeComponent>("Running Migrations {initialState} to {finalState}", plan.InitialState, plan.FinalState); var upgrade = databaseBuilder.UpgradeSchemaAndData(plan); if (!upgrade.Success) { throw new Exception("Upgrade Failed - Upgrade Schema"); } // Step: 'SetUmbracoVersionStep' // Update the version number inside the web.config logger.Debug <SilentUpgradeComponent>("Updating version in the web.config {version}", UmbracoVersion.SemanticVersion.ToSemanticString()); // Doing this essentially restats the site. globalSettings.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString(); // put something in the log. logger.Info <SilentUpgradeComponent>("Silent Upgrade Completed {version}", UmbracoVersion.SemanticVersion.ToSemanticString()); Upgraded = true; } catch (Exception ex) { logger.Warn <SilentUpgradeComponent>(ex, "Silent Upgrade Failed"); Upgraded = false; // if this is false, we should fall through to the 'standard' upgrade path. } }
public void Initialize() { if (runtimeState.Level <= RuntimeLevel.Run) { logger.Info <uSyncBackofficeComponent>("Umbraco is not in Run Mode {0} so uSync is not going to run", runtimeState.Level); return; } if (runtimeState.ServerRole == Umbraco.Core.Sync.ServerRole.Replica) { logger.Info <uSyncBackofficeComponent>("This is a replica server, uSync will not run any of the startup events"); return; } using (logger.DebugDuration <uSyncBackofficeComponent>("uSync Starting")) { InitBackOffice(); } }
public override Task <bool> PerformRunAsync(CancellationToken token) { if (RunOnThisServer()) { logger.Info <CustomBackgroundTask>("Running our task"); } ; // technically we shoud run things async for performances // because we are doing nothing here, just return the task. return(Task.FromResult <bool>(true)); }
public override bool PerformRun() { try { var service = new ITweetService(); service.RebuildIndex("TweetIndex"); } catch (Exception ex) { _logger.Info <TweetPopulateIndex>("The following error occured with the Scheduled task used to rebuild the Tweet Index : {ErrorMessage}", ex); } // If we want to keep repeating - we need to return true // But if we run into a problem/error & want to stop repeating - return false return(true); }
public void Migrate() { using (UmbracoContextReference umbracoContextReference = _context.EnsureUmbracoContext()) { using (var scope = _scopeProvider.CreateScope()) { var adminGroup = _userService.GetUserGroupByAlias(Constants.Security.AdminGroupAlias); adminGroup.AddAllowedSection("uiExamples"); _userService.Save(adminGroup); scope.Complete(); } } _logger.Info <AddSectionForAdmins>("Post migration completed"); }
public async override Task <bool> PerformRunAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { _logger.Warn(GetType(), "Background task cancellation requested in {Type:l}.", GetType()); return(false); } _logger.Info <OnlySportCsvExportTask>(nameof(OnlySportCsvExportTask) + " running"); var matches = (await _matchDataSource.ReadMatchListings(new MatchFilter { FromDate = DateTimeOffset.UtcNow }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false)).Select(x => new OnlySportCsvRecord { MatchId = x.MatchId.GetHashCode() > 0 ? x.MatchId.GetHashCode() : x.MatchId.GetHashCode() * -1, Title = x.MatchName, StartTime = x.StartTime.ToUnixTimeSeconds(), Latitude = x.MatchLocation?.Latitude, Longitude = x.MatchLocation?.Longitude, Website = "https://www.stoolball.org.uk" + x.MatchRoute, Description = x.Description() }).ToList(); var path = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"App_Data\csv"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } using (var writer = new StreamWriter(Path.Combine(path, "onlysport.csv"))) { using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) { csv.WriteRecords(matches); } } // Keep repeating return(true); }
public void Initialize() { /* * foreach (var index in _indexCreator.Create()) * { * _examineManager.AddIndex(index); * ElasticSearchBaseIndex luceneBaseIndex = (ElasticSearchBaseIndex) index; * } */ _logger.Debug <ElasticSearchExamineComponent>("Examine shutdown registered with MainDom"); var registeredIndexers = _examineManager.Indexes.OfType <IIndex>().Count(); _logger.Info <ExamineComponent>("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers); // don't bind event handlers if we're not suppose to listen if (registeredIndexers == 0) { return; } }
internal IEnumerable <Type> SortComposers(Dictionary <Type, List <Type> > requirements) { // sort composers var graph = new TopoGraph <Type, KeyValuePair <Type, List <Type> > >(kvp => kvp.Key, kvp => kvp.Value); graph.AddItems(requirements); List <Type> sortedComposerTypes; try { sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).Where(x => !x.IsInterface).ToList(); } catch (Exception e) { // in case of an error, force-dump everything to log _logger.Info <Composers>("Composer Report:\r\n{ComposerReport}", GetComposersReport(requirements)); _logger.Error <Composers>(e, "Failed to sort composers."); throw; } return(sortedComposerTypes); }
public IEnumerable <uSyncAction> ImportAll(string folder, HandlerSettings config, bool force, SyncUpdateCallback callback = null) { logger.Info <uSync8BackOffice>("Running Import: {0}", Path.GetFileName(folder)); var actions = new List <uSyncAction>(); var updates = new Dictionary <string, TObject>(); actions.AddRange(ImportFolder(folder, config, updates, force, callback)); if (updates.Any()) { int count = 0; foreach (var update in updates) { count++; callback?.Invoke($"Second Pass {Path.GetFileName(update.Key)}", count, updates.Count); ImportSecondPass(update.Key, update.Value, config, callback); } } callback?.Invoke("Done", 1, 1); return(actions); }
public override bool PerformRun() { const string spreakerApiEpisodesUrlFormat = "https://api.spreaker.com/v2/shows/{0}/episodes"; const string spreakerApiEpisodeUrlFormat = "https://api.spreaker.com/v2/episodes/{0}"; if (!AppSettings.CandidContribs.SpreakerApi.Enabled) { _logger.Info <SpreakerFeed>("Spreaker episode import disabled"); return(false); } _logger.Info <SpreakerFeed>("Spreaker episode import started"); using (var cref = _context.EnsureUmbracoContext()) { // get episodes folder to add episodes to var cache = cref.UmbracoContext.Content; var cmsEpisodesFolder = (EpisodesFolder)cache.GetByXPath("//episodesFolder").FirstOrDefault(); if (cmsEpisodesFolder == null) { _logger.Error <SpreakerFeed>("Spreaker episode import failed: no EpisodesFolder found"); return(false); } var episodesApiUrl = string.Format(spreakerApiEpisodesUrlFormat, AppSettings.CandidContribs.SpreakerApi.ShowId); var response = client.GetAsync(episodesApiUrl).Result; if (!response.IsSuccessStatusCode) { _logger.Error <SpreakerFeed>("Spreaker episode import failed: response code {0}, url {1}", response.StatusCode, episodesApiUrl); return(false); } // get API response for all episodes var episodesString = response.Content.ReadAsStringAsync().Result; var convertedEps = JsonConvert.DeserializeObject <APIResponse>(episodesString); // get episodes in ascending date order before trying to add to CMS var episodes = convertedEps.Response.Items.OrderBy(x => x.PublishedDate); foreach (var episode in episodes) { // is this the best way to find by API id? var cmsEpisode = cmsEpisodesFolder.SearchChildren(episode.Id.ToString()).FirstOrDefault(); if (cmsEpisode != null) { // already exists so nothing to do continue; } var episodeDetailsUrl = string.Format(spreakerApiEpisodeUrlFormat, episode.Id); var episodeDetailsResponse = client.GetAsync(episodeDetailsUrl).Result; if (!episodeDetailsResponse.IsSuccessStatusCode) { _logger.Error <SpreakerFeed>("Spreaker episode import failed: response code {0}, url {1}", response.StatusCode, episodeDetailsUrl); continue; } var episodeString = episodeDetailsResponse.Content.ReadAsStringAsync().Result; var convertedEp = JsonConvert.DeserializeObject <APIResponse>(episodeString); AddNewEpisode(convertedEp.Response.Episode, cmsEpisodesFolder); } } _logger.Info <SpreakerFeed>("Spreaker episode import finished"); return(true); }
public bool PurgeCache(string zoneIdentifier, IEnumerable <string> urls, bool purgeEverything = false, bool throwExceptionOnError = false) { try { if (String.IsNullOrEmpty(zoneIdentifier)) { throw new ArgumentNullException("zoneIdentifier"); } if ((urls == null || !urls.Any()) && !purgeEverything) { //Its probably worthy to log that we were going to purge pages but no url was given logger.Info <CloudflareService>("PurgeIndividualPages was called but there were no urls given to purge nor are we purging everything"); return(true); } using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); string json; if (purgeEverything) { json = "{\"purge_everything\":true}"; } else { json = String.Format("{{\"files\":{0}}}", JsonConvert.SerializeObject(urls)); } HttpRequestMessage request = new HttpRequestMessage() { RequestUri = new Uri(CLOUDFLARE_API_BASE_URL + "zones/" + zoneIdentifier + "/purge_cache"), Method = HttpMethod.Delete, Content = new StringContent(json, Encoding.UTF8, "application/json") }; AddRequestHeaders(request); var responseContent = client.SendAsync(request).Result.Content; var stringVersion = responseContent.ReadAsStringAsync().Result; try { BasicCloudflareResponse response = responseContent.ReadAsAsync <BasicCloudflareResponse>().Result; if (!response.Success) { //Something went wrong log the response logger.Error <CloudflareService>(String.Format("Something went wrong because of {0}", response.Messages.ToString())); return(false); } } catch (Exception e) { logger.Error <CloudflareService>(String.Format("Something went wrong getting the purge cache response back. The url that was used is {0}. The json that was used is {1}. The raw string value is {1}", request.RequestUri.ToString(), json, stringVersion), e); return(false); } return(true); } } catch (Exception e) { logger.Error <CloudflareService>(String.Format("Failed to purge individual pages for urls {0}", urls.Select(x => { return(x + "x"); })), e); if (throwExceptionOnError) { throw e; } else { return(false); } } }
public async override Task <bool> PerformRunAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { _logger.Warn(GetType(), "Background task cancellation requested in {Type:l}.", GetType()); return(false); } _logger.Info <SpogoCsvExportTask>(nameof(SpogoCsvExportTask) + " running"); var teams = (await _teamDataSource.ReadTeams(new TeamFilter { ActiveTeams = true, TeamTypes = new List <TeamType?> { TeamType.Regular } }).ConfigureAwait(false)).Select(x => new SpogoCsvRecord { TeamId = x.TeamId.Value.GetHashCode() > 0 ? x.TeamId.Value.GetHashCode() : x.TeamId.Value.GetHashCode() * -1, TeamName = x.TeamName + " Stoolball Club", Description = FormatTeamDescription(x), PlayerType = x.PlayerType.Humanize(), HomeGroundName = x.MatchLocations.FirstOrDefault()?.Name(), StreetName = x.MatchLocations.FirstOrDefault()?.StreetDescription, Locality = x.MatchLocations.FirstOrDefault()?.Locality, Town = x.MatchLocations.FirstOrDefault()?.Town, AdministrativeArea = x.MatchLocations.FirstOrDefault()?.AdministrativeArea, Postcode = x.MatchLocations.FirstOrDefault()?.Postcode, Country = "England", Latitude = x.MatchLocations.FirstOrDefault()?.Latitude, Longitude = x.MatchLocations.FirstOrDefault()?.Longitude, Website = !string.IsNullOrWhiteSpace(x.Website) ? x.Website : "https://www.stoolball.org.uk" + x.TeamRoute, ContactEmail = _contactDetailsParser.ParseFirstEmailAddress(x.PublicContactDetails), ContactPhone = _contactDetailsParser.ParseFirstPhoneNumber(x.PublicContactDetails) }).Where(x => !string.IsNullOrEmpty(x.ContactEmail) || !string.IsNullOrEmpty(x.ContactPhone)).ToList(); var path = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"App_Data\csv"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } using (var writer = new StreamWriter(Path.Combine(path, "spogo-protected.csv"))) { using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) { csv.WriteRecords(teams); } } foreach (var team in teams) { team.ContactEmail = team.ContactPhone = string.Empty; } using (var writer = new StreamWriter(Path.Combine(path, "spogo.csv"))) { using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) { csv.WriteRecords(teams); } } // Keep repeating return(true); }
public void Migrate() { logger.Info <RebuildSomething>("Post Migration Step Ran"); }