private async Task <string> TrySaveFlags(FeatureFlagsViewModel model, string contentId)
        {
            var flags = new FeatureFlags(
                model.Features.ToDictionary(f => f.Name, f => f.Status),
                model.Flights.ToDictionary(f => f.Name, f => f.AsFlight()));

            var result = await _storage.TrySaveAsync(flags, contentId);

            switch (result)
            {
            case FeatureFlagSaveResult.Ok:
                // The flags have been persisted. Refresh this instance's cache immediately.
                await _cache.RefreshAsync();

                var refreshSeconds = _config.FeatureFlagsRefreshInterval.TotalSeconds;
                TempData["Message"] = $"Your feature flags have been saved! It may take up to {refreshSeconds} seconds for this change to propagate everywhere.";
                return(null);

            case FeatureFlagSaveResult.Conflict:
                return("Your changes were not applied as the feature flags were modified by someone else. Please reload the page and try again.");

            default:
                return($"Unknown save result '{result}'.");
            }
        }
Esempio n. 2
0
        public async Task <ActionResult> Index(FeatureFlagsViewModel model)
        {
            if (ModelState.IsValid)
            {
                var result = await _storage.TrySaveAsync(model.Flags, model.ContentId);

                switch (result.Type)
                {
                case FeatureFlagSaveResultType.Ok:
                    // The flags have been persisted. Refresh this instance's cache immediately.
                    await _cache.RefreshAsync();

                    var refreshSeconds = _config.FeatureFlagsRefreshInterval.TotalSeconds;

                    TempData["Message"] = $"Your feature flags have been saved! It may take up to {refreshSeconds} seconds for this change to propagate everywhere.";
                    return(Redirect(Url.Action(actionName: "Index", controllerName: "Features")));

                case FeatureFlagSaveResultType.Conflict:
                    TempData["ErrorMessage"] = "Your changes were not applied as the feature flags were modified by someone else. " +
                                               "Please reload the page and try again.";
                    break;

                case FeatureFlagSaveResultType.Invalid:
                    ModelState.AddModelError(nameof(model.Flags), $"Invalid flags: {result.Message}");
                    break;

                default:
                    TempData["ErrorMessage"] = $"Unknown save result '{result}': {result.Message}.";
                    break;
                }
            }

            return(View(model));
        }
        private string ApplyChange <TModify, TBase>(
            FeatureFlagsViewModel model,
            TModify change,
            ChangeType type)
            where TModify : IModifyFeatureFlagsViewModel <TBase>, TBase
            where TBase : IFeatureFlagsObjectViewModel
        {
            var validationError = change.GetValidationError(_userService);

            if (validationError != null)
            {
                return(validationError);
            }

            var existingList = change.GetExistingList(model);
            var existing     = existingList.SingleOrDefault(f => f.Name == change.Name);

            switch (type)
            {
            case ChangeType.Add:
                if (existing == null)
                {
                    existingList.Add(change);
                    return(null);
                }
                else
                {
                    return($"The {change.PrettyName} '{change.Name}' already exists. " +
                           $"You cannot add a {change.PrettyName} that already exists.");
                }

            case ChangeType.Edit:
                if (existing == null)
                {
                    return($"The {change.PrettyName} '{change.Name}' does not exist. " +
                           $"You cannot edit a {change.PrettyName} that does not exist.");
                }
                else
                {
                    change.ApplyTo(existing);
                    return(null);
                }

            case ChangeType.Delete:
                if (existing == null)
                {
                    return($"The {change.PrettyName} '{change.Name}' does not exist. " +
                           $"You cannot delete a {change.PrettyName} that does not exist.");
                }
                else
                {
                    existingList.Remove(existing);
                    return(null);
                }

            default:
                throw new ArgumentOutOfRangeException(nameof(type));
            }
        }
        public static void AssertFlags(FeatureFlags flags, FeatureFlagsViewModel model)
        {
            Assert.Equal(flags.Features.Count, model.Features.Count);
            Assert.Equal(flags.Flights.Count, model.Flights.Count);

            foreach (var feature in model.Features)
            {
                Assert.True(flags.Features.ContainsKey(feature.Name));
                Assert.Equal(flags.Features[feature.Name], feature.Status);
            }

            foreach (var flight in model.Flights)
            {
                Assert.True(flags.Flights.ContainsKey(flight.Name));
                AssertFlight(flags.Flights[flight.Name], flight);
            }
        }
        public static void AssertFlags(
            FeatureFlags flags,
            FeatureFlagsViewModel model,
            bool hasLastUpdated,
            TimeSpan refreshInterval,
            string contentId)
        {
            if (hasLastUpdated)
            {
                Assert.True(model.TimeSinceLastRefresh > TimeSpan.Zero);
            }
            else
            {
                Assert.Null(model.TimeSinceLastRefresh);
            }

            Assert.Equal(refreshInterval, model.RefreshInterval);
            Assert.Equal(contentId, model.ContentId);

            AssertFlags(flags, model);
        }