예제 #1
0
        public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context)
        {
            DoActionSelectTemplatesToPullFromEnvironmentBlock thisBlock = this;

            Condition.Requires(arg).IsNotNull(thisBlock.Name + ": The entity view cannot be null.");

            if (string.IsNullOrEmpty(arg.Action) || (!arg.Action.Equals(context.GetPolicy <KnownComposerActionsPolicy>().SelectTemplatesToPullFromEnvironment, StringComparison.OrdinalIgnoreCase)))
            {
                return(await Task.FromResult(arg));
            }

            KnownResultCodes errorsCodes         = context.CommerceContext.GetPolicy <KnownResultCodes>();
            ViewProperty     environmentProperty = arg.GetProperty(ComposerConstants.EnvironmentDropdownPropertyName);
            string           propertyDisplayName = environmentProperty == null ? ComposerConstants.EnvironmentDropdownPropertyDisplayName : environmentProperty.DisplayName;

            if (string.IsNullOrEmpty(environmentProperty?.Value))
            {
                string str = await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[1]
                {
                    propertyDisplayName
                }, "Invalid or missing value for property '" + propertyDisplayName + "'.").ConfigureAwait(false);

                return(arg);
            }

            // get ids from view
            string[] templateIds = arg.GetProperties(p => p.UiType.Equals("Options", StringComparison.OrdinalIgnoreCase))
                                   .Where(property => {
                bool result;
                bool.TryParse(property.Value, out result);
                return(result);
            })
                                   .Select(property => property.Name)
                                   .ToArray();

            if (templateIds == null || templateIds.Length <= 0)
            {
                return(arg);
            }

            var composerTemplates = (await thisBlock._getProxyComposerTemplatesPipeline.Run(new GetProxyComposerTemplatesArgument(templateIds, environmentProperty.Value), context).ConfigureAwait(false))
                                    .ToList();

            if (composerTemplates == null || !composerTemplates.Any())
            {
                string str = await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[1]
                {
                    propertyDisplayName
                }, "Invalid or missing value for property '" + propertyDisplayName + "'.").ConfigureAwait(false);

                return(arg);
            }

            foreach (var template in composerTemplates)
            {
                await this._commander.CreateTemplateFromProxy(context.CommerceContext, template);
            }

            return(arg);
        }
예제 #2
0
        public async override Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Condition.Requires(entityView).IsNotNull($"{Name}: The argument cannot be null.");

            // Only proceed if the right action was invoked
            if (string.IsNullOrEmpty(entityView.Action) || !entityView.Action.StartsWith("Edit-", StringComparison.OrdinalIgnoreCase))
            {
                return(entityView);
            }

            // Get the commerce entity from the context
            var commerceEntity = context.CommerceContext.GetObject <CommerceEntity>(x => x.Id.Equals(entityView.EntityId));

            if (commerceEntity == null)
            {
                return(entityView);
            }

            KnownResultCodes errorCodes = context.CommerceContext.GetPolicy <KnownResultCodes>();

            if (context.CommerceContext.AnyMessage(msg => msg.Code == errorCodes.ValidationError))
            {   // We found an error
                return(entityView);
            }

            var components = commerceEntity.Components;

            if (!string.IsNullOrWhiteSpace(entityView.ItemId) && commerceEntity is SellableItem)
            {
                var variation = ((SellableItem)commerceEntity).GetVariation(entityView.ItemId);
                if (variation != null)
                {
                    components = variation.ChildComponents;
                }
            }

            var allComponentTypes   = catalogSchemaCommander.GetAllComponentTypes();
            var editedComponentType = allComponentTypes.SingleOrDefault(compType => entityView.Action == $"Edit-{compType.FullName}");
            var editedComponent     = components.SingleOrDefault(comp => entityView.Action == $"Edit-{comp.GetType().FullName}");

            if (editedComponent == null)
            {
                editedComponent = (Sitecore.Commerce.Core.Component)Activator.CreateInstance(editedComponentType);
                components.Add(editedComponent);
            }

            if (editedComponent != null)
            {
                catalogSchemaCommander.SetPropertyValuesOnEditedComponent(entityView.Properties, editedComponent.GetType(), editedComponent, context.CommerceContext);

                // Persist changes
                await this.catalogSchemaCommander.Pipeline <IPersistEntityPipeline>().Run(new PersistEntityArgument(commerceEntity), context);
            }

            return(await Task.FromResult(entityView));
        }
        public virtual async Task CreateTemplateFromProxy(CommerceContext commerceContext, ProxyComposer.ComposerTemplate proxyComposerTemplate)
        {
            ComposerCommander composerCommander = this;

            Condition.Requires(commerceContext).IsNotNull("CommerceContext");
            Condition.Requires(proxyComposerTemplate).IsNotNull("composerTemplate");
            using (CommandActivity.Start(commerceContext, composerCommander))
            {
                KnownResultCodes errorCodes           = commerceContext.GetPolicy <KnownResultCodes>();
                string           composerTemplateName = proxyComposerTemplate.Name;
                if (string.IsNullOrEmpty(composerTemplateName))
                {
                    string composerTemplatePropertyName = "Name";
                    string str2 = await commerceContext.AddMessage(errorCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[1]
                    {
                        composerTemplatePropertyName
                    }, "Invalid or missing value for property '" + composerTemplatePropertyName + "'.").ConfigureAwait(false);

                    return;
                }
                string templateId = proxyComposerTemplate.Id;
                if (await composerCommander.GetEntity <ComposerTemplate>(commerceContext, templateId, false).ConfigureAwait(false) != null)
                {
                    string str = await commerceContext.AddMessage(errorCodes.ValidationError, "NameAlreadyInUse", new object[1]
                    {
                        proxyComposerTemplate.Name
                    }, "Name '" + proxyComposerTemplate.Name + "' is already in use.").ConfigureAwait(false);

                    return;
                }

                ComposerTemplate engineComposerTemplate = new ComposerTemplate(templateId);
                engineComposerTemplate.Name           = proxyComposerTemplate.Name;
                engineComposerTemplate.DisplayName    = proxyComposerTemplate.DisplayName;
                engineComposerTemplate.FriendlyId     = proxyComposerTemplate.Name;
                engineComposerTemplate.LinkedEntities = proxyComposerTemplate.LinkedEntities;

                this.AddTagsFromProxy(engineComposerTemplate, proxyComposerTemplate);
                this.AddComposerTemplateListMembershipsFromProxy(engineComposerTemplate, proxyComposerTemplate);
                await this.AddComposerTemplateEntityViewFromProxy(commerceContext, engineComposerTemplate, proxyComposerTemplate);

                this.AddItemDefinitionsFromProxy(engineComposerTemplate, proxyComposerTemplate);

                int num = await composerCommander.PersistEntity(commerceContext, engineComposerTemplate).ConfigureAwait(false) ? 1 : 0;

                errorCodes = null;
                templateId = null;
            }
        }
예제 #4
0
        public async override Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Condition.Requires(entityView).IsNotNull($"{Name}: The argument cannot be null.");

            // Only proceed if the right action was invoked
            if (string.IsNullOrEmpty(entityView.Action) || !entityView.Action.StartsWith("Edit-", StringComparison.OrdinalIgnoreCase))
            {
                return(entityView);
            }

            // Get the sellable item from the context
            var sellableItem = context.CommerceContext.GetObject <SellableItem>(x => x.Id.Equals(entityView.EntityId));

            if (sellableItem == null)
            {
                return(entityView);
            }

            KnownResultCodes errorCodes = context.CommerceContext.GetPolicy <KnownResultCodes>();

            if (context.CommerceContext.AnyMessage(msg => msg.Code == errorCodes.ValidationError))
            {   // We found an error
                return(entityView);
            }

            var applicableComponentTypes = await this.catalogSchemaCommander.GetApplicableComponentTypes(context.CommerceContext, sellableItem);

            var editedComponentType = applicableComponentTypes.SingleOrDefault(comp => entityView.Action == $"Edit-{comp.FullName}");

            if (editedComponentType != null)
            {
                // Get the component from the sellable item or its variation
                var editedComponent = catalogSchemaCommander.GetEditedComponent(sellableItem, entityView.ItemId, editedComponentType);

                // Set the properties from the view on the component
                catalogSchemaCommander.SetPropertyValuesOnEditedComponent(entityView.Properties, editedComponentType, editedComponent, context.CommerceContext);

                // Persist changes
                await this.catalogSchemaCommander.Pipeline <IPersistEntityPipeline>().Run(new PersistEntityArgument(sellableItem), context);
            }

            return(entityView);
        }
        private async Task <bool> ValidateProperty(System.Reflection.PropertyInfo prop, string fieldValueAsString, Attribute[] propAttributes, PropertyAttribute propertyAttribute, CommercePipelineExecutionContext context)
        {
            var validationAttributes = propAttributes.OfType <ValidationAttribute>();
            var validationResults    = new List <ValidationResult>();

            var valid = Validator.TryValidateValue(fieldValueAsString, new ValidationContext(fieldValueAsString, null, null), validationResults, validationAttributes);

            if (!valid)
            {
                foreach (var validationResult in validationResults)
                {
                    KnownResultCodes errorCodes = context.CommerceContext.GetPolicy <KnownResultCodes>();
                    var str = await context.CommerceContext.AddMessage(errorCodes.ValidationError, "InvalidPropertyValueRange", new object[1]
                    {
                        propertyAttribute?.DisplayName ?? prop.Name
                    }, $"There was an error for '{ propertyAttribute?.DisplayName ?? prop.Name }': '{validationResult.ErrorMessage}'.");
                }
            }

            return(valid);
        }
        public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context)
        {
            if (string.IsNullOrEmpty(arg?.Action) ||
                !arg.Action.Equals(context.GetPolicy <KnownCustomPricingActionsPolicy>().SelectMembershipCurrency, StringComparison.OrdinalIgnoreCase) ||
                !arg.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomRow, StringComparison.OrdinalIgnoreCase))
            {
                return(arg);
            }

            var card = context.CommerceContext.GetObjects <PriceCard>().FirstOrDefault(p => p.Id.Equals(arg.EntityId, StringComparison.OrdinalIgnoreCase));

            if (card == null)
            {
                return(arg);
            }

            KnownResultCodes policy = context.GetPolicy <KnownResultCodes>();

            if (string.IsNullOrEmpty(arg.ItemId))
            {
                await context.CommerceContext.AddMessage(policy.ValidationError, "InvalidOrMissingPropertyValue",
                                                         new object[] { "ItemId" }, "Invalid or missing value for property 'ItemId'.")
                .ConfigureAwait(false);

                return(arg);
            }

            PriceSnapshotComponent snapshot = card.Snapshots.FirstOrDefault(s => s.Id.Equals(arg.ItemId, StringComparison.OrdinalIgnoreCase));

            if (snapshot == null)
            {
                await context.CommerceContext.AddMessage(policy.ValidationError, "PriceSnapshotNotFound",
                                                         new object[] { arg.ItemId, card.FriendlyId }, "Price snapshot " + arg.ItemId + " on price card " + card.FriendlyId + " was not found.")
                .ConfigureAwait(false);

                return(arg);
            }

            var currencyProperty = arg.Properties.FirstOrDefault(p => p.Name.Equals("Currency", StringComparison.OrdinalIgnoreCase));

            string currency = currencyProperty?.Value;

            if (string.IsNullOrEmpty(currency))
            {
                await context.CommerceContext.AddMessage(policy.ValidationError, "InvalidOrMissingPropertyValue",
                                                         new object[] { currencyProperty == null ? "Currency" : currencyProperty.DisplayName }, "Invalid or missing value for property 'Currency'.")
                .ConfigureAwait(false);

                return(arg);
            }

            if (snapshot.Tiers.Any(t => t.Currency.Equals(currency, StringComparison.OrdinalIgnoreCase)))
            {
                await context.CommerceContext.AddMessage(policy.ValidationError, "CurrencyAlreadyExists",
                                                         new object[] { currency, snapshot.Id, card.FriendlyId }, "Currency " + currency + " already exists for snapshot " + snapshot.Id + " on price card " + card.FriendlyId + ".")
                .ConfigureAwait(false);

                return(arg);
            }

            CurrencySet currencySet  = null;
            string      entityTarget = (await _findEntityCommand.Process(context.CommerceContext, typeof(PriceBook), card.Book.EntityTarget, false).ConfigureAwait(false) as PriceBook)?.CurrencySet.EntityTarget;

            if (!string.IsNullOrEmpty(entityTarget))
            {
                currencySet = await _getCurrencySetCommand.Process(context.CommerceContext, entityTarget).ConfigureAwait(false);

                if (currencySet != null)
                {
                    var    currencies = currencySet.GetComponent <CurrenciesComponent>().Currencies;
                    string str        = string.Join(", ", currencies.Select(c => c.Code));

                    if (!currencies.Any(c => c.Code.Equals(currency, StringComparison.OrdinalIgnoreCase)))
                    {
                        CommercePipelineExecutionContext executionContext = context;
                        CommerceContext commerceContext = context.CommerceContext;
                        string          validationError = context.GetPolicy <KnownResultCodes>().ValidationError;
                        string          commerceTermKey = "InvalidCurrency";
                        var             args            = new object[] { currency, str };
                        string          defaultMessage  = "Invalid currency '" + currency + "'. Valid currencies are '" + str + "'.";
                        executionContext.Abort(await commerceContext.AddMessage(validationError, commerceTermKey, args, defaultMessage).ConfigureAwait(false), context);
                        executionContext = null;

                        return(arg);
                    }
                }
            }

            currencyProperty.IsReadOnly = true;
            currencyProperty.Policies   = new List <Policy>()
            {
                new AvailableSelectionsPolicy(currencySet == null ||
                                              !currencySet.HasComponent <CurrenciesComponent>() ?  new List <Selection>() :  currencySet.GetComponent <CurrenciesComponent>()
                                              .Currencies.Select(c =>
                {
                    return(new Selection()
                    {
                        DisplayName = c.Code,
                        Name = c.Code
                    });
                }).ToList(), false)
            };

            EntityView priceCustomCellEntityView = new EntityView
            {
                Name     = context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomCell,
                EntityId = card.Id,
                ItemId   = snapshot.Id
            };

            var membershipLevels        = context.GetPolicy <MembershipLevelPolicy>().MembershipLevels;
            List <Selection> selections = currencySet == null || !currencySet.HasComponent <CurrenciesComponent>() ? new List <Selection>() : membershipLevels.Select(c =>
            {
                return(new Selection()
                {
                    DisplayName = c.MemerbshipLevelName,
                    Name = c.MemerbshipLevelName
                });
            }).ToList();

            AvailableSelectionsPolicy availableSelectionsPolicy = new AvailableSelectionsPolicy(selections, false);

            List <Policy> commercePolicies = new List <Policy>()
            {
                availableSelectionsPolicy
            };

            ViewProperty membershipLevelViewProperty = new ViewProperty()
            {
                Name         = "MembershipLevel",
                OriginalType = typeof(string).FullName,
                Policies     = commercePolicies
            };

            priceCustomCellEntityView.Properties.Add(membershipLevelViewProperty);

            ViewProperty quantityViewProperty = new ViewProperty();

            quantityViewProperty.Name         = "Quantity";
            quantityViewProperty.OriginalType = typeof(decimal).FullName;
            priceCustomCellEntityView.Properties.Add(quantityViewProperty);

            ViewProperty priceViewProperty = new ViewProperty
            {
                Name         = "Price",
                RawValue     = null,
                OriginalType = typeof(decimal).FullName
            };

            priceCustomCellEntityView.Properties.Add(priceViewProperty);
            arg.ChildViews.Add(priceCustomCellEntityView);
            arg.UiHint = "Grid";
            context.CommerceContext.AddModel(new MultiStepActionModel(context.GetPolicy <KnownCustomPricingActionsPolicy>().AddMembershipCurrency));

            return(arg);
        }
        public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context)
        {
            if (string.IsNullOrEmpty(arg?.Action) ||
                !arg.Action.Equals(context.GetPolicy <KnownCustomPricingActionsPolicy>().EditMembershipCurrency, StringComparison.OrdinalIgnoreCase) ||
                !arg.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomRow, StringComparison.OrdinalIgnoreCase))
            {
                return(arg);
            }

            PriceCard card = context.CommerceContext.GetObjects <PriceCard>().FirstOrDefault(p => p.Id.Equals(arg.EntityId, StringComparison.OrdinalIgnoreCase));

            if (card == null)
            {
                return(arg);
            }

            KnownResultCodes errorsCodes = context.GetPolicy <KnownResultCodes>();

            if (string.IsNullOrEmpty(arg.ItemId))
            {
                await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { "ItemId" }, "Invalid or missing value for property 'ItemId'.")
                .ConfigureAwait(false);

                return(arg);
            }

            string snapshotId = arg.ItemId.Split('|')[0];
            PriceSnapshotComponent snapshot = card.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotId, StringComparison.OrdinalIgnoreCase));

            if (snapshot == null)
            {
                await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "PriceSnapshotNotFound", new object[] { snapshotId, card.FriendlyId }, "Price snapshot " + snapshotId + " on price card " + card.FriendlyId + " was not found.")
                .ConfigureAwait(false);

                return(arg);
            }

            ViewProperty currency = arg.Properties.FirstOrDefault(p => p.Name.Equals("Currency", StringComparison.OrdinalIgnoreCase));

            if (string.IsNullOrEmpty(currency?.Value))
            {
                await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { currency == null ? "Currency" : currency.DisplayName }, "Invalid or missing value for property 'Currency'.")
                .ConfigureAwait(false);

                return(arg);
            }

            List <Model> list = arg.ChildViews.Where(v => v.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomCell, StringComparison.OrdinalIgnoreCase))
                                .ToList();

            if (!list.Any())
            {
                await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { "Tiers" }, "Invalid or missing value for property 'Tiers'.")
                .ConfigureAwait(false);

                return(arg);
            }

            List <CustomPriceTier> tiersToAdd    = new List <CustomPriceTier>();
            List <CustomPriceTier> tiersToEdit   = new List <CustomPriceTier>();
            List <CustomPriceTier> tiersToDelete = new List <CustomPriceTier>();
            bool hasError = false;

            foreach (EntityView entityView in list.Cast <EntityView>())
            {
                ViewProperty quantityViewProperty = entityView.Properties.FirstOrDefault(p => p.Name.Equals("Quantity", StringComparison.OrdinalIgnoreCase));
                decimal      quantity;

                if (!decimal.TryParse(quantityViewProperty?.Value, out quantity))
                {
                    await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { quantityViewProperty == null ? "Quantity" : quantityViewProperty.DisplayName }, "Invalid or missing value for property 'Quantity'.")
                    .ConfigureAwait(false);

                    hasError = true;
                }
                else
                {
                    ViewProperty membershipLevel = entityView.Properties.FirstOrDefault(p => p.Name.Equals("MembershipLevel", StringComparison.OrdinalIgnoreCase));

                    if (string.IsNullOrEmpty(currency?.Value))
                    {
                        await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { currency == null ? "MembershipLevel" : currency.DisplayName }, "Invalid or missing value for property 'MembershipLevel'.")
                        .ConfigureAwait(false);

                        hasError = true;
                    }
                    else
                    {
                        ViewProperty priceViewProperty = entityView.Properties.FirstOrDefault(p => p.Name.Equals("Price", StringComparison.OrdinalIgnoreCase));
                        decimal      result;
                        bool         isPriceParsed            = decimal.TryParse(priceViewProperty?.Value, out result);
                        var          membershipTiersComponent = snapshot.GetComponent <MembershipTiersComponent>();

                        CustomPriceTier priceTier = membershipTiersComponent.Tiers.FirstOrDefault(t => t.Currency == currency.Value && t.Quantity == quantity && t.MembershipLevel == membershipLevel.Value);

                        if (priceTier == null)
                        {
                            if (!isPriceParsed)
                            {
                                await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { priceViewProperty == null ? "Price" : priceViewProperty.DisplayName }, "Invalid or missing value for property 'Price'.")
                                .ConfigureAwait(false);

                                hasError = true;
                            }
                            else
                            {
                                tiersToAdd.Add(new CustomPriceTier(currency.Value, quantity, result, membershipLevel.Value));
                            }
                        }
                        else if (!isPriceParsed)
                        {
                            tiersToDelete.Add(priceTier);
                        }
                        else
                        {
                            priceTier.Price           = result;
                            priceTier.Quantity        = quantity;
                            priceTier.MembershipLevel = membershipLevel.Value;
                            tiersToEdit.Add(priceTier);
                        }
                    }
                }
            }

            if (hasError)
            {
                return(arg);
            }

            if (tiersToAdd.Any())
            {
                await _addPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToAdd)
                .ConfigureAwait(false);
            }

            if (tiersToDelete.Any() && !context.CommerceContext.HasErrors())
            {
                await _removeCustomPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToDelete)
                .ConfigureAwait(false);
            }

            if (tiersToEdit.Any() && !context.CommerceContext.HasErrors())
            {
                await _editPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToEdit)
                .ConfigureAwait(false);
            }

            return(arg);
        }
예제 #8
0
        public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context)
        {
            DoActionSelectCommerceEngineEnvironmentToPullTemplatesBlock thisBlock = this;

            Condition.Requires(arg).IsNotNull(thisBlock.Name + ": The entity view cannot be null.");

            if (string.IsNullOrEmpty(arg.Action) || (!arg.Action.Equals(context.GetPolicy <KnownComposerActionsPolicy>().SelectCommerceEngineEnvironmentToPullTemplates, StringComparison.OrdinalIgnoreCase)))
            {
                return(await Task.FromResult(arg));
            }

            KnownResultCodes errorsCodes         = context.CommerceContext.GetPolicy <KnownResultCodes>();
            ViewProperty     environmentProperty = arg.GetProperty(ComposerConstants.EnvironmentDropdownPropertyName);
            string           propertyDisplayName = environmentProperty == null ? ComposerConstants.EnvironmentDropdownPropertyDisplayName : environmentProperty.DisplayName;

            if (string.IsNullOrEmpty(environmentProperty?.Value))
            {
                string str = await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[1]
                {
                    propertyDisplayName
                }, "Invalid or missing value for property '" + propertyDisplayName + "'.").ConfigureAwait(false);

                return(arg);
            }


            var composerTemplates = (await thisBlock._getProxyComposerTemplatesPipeline.Run(new GetProxyComposerTemplatesArgument(null, environmentProperty.Value), context).ConfigureAwait(false))
                                    .ToList();

            if (composerTemplates == null || !composerTemplates.Any())
            {
                string str = await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[1]
                {
                    propertyDisplayName
                }, "Invalid or missing value for property '" + propertyDisplayName + "'.").ConfigureAwait(false);

                return(arg);
            }

            environmentProperty.RawValue   = environmentProperty.Value;
            environmentProperty.IsReadOnly = true;
            ViewProperty newEnvironmentProperty = environmentProperty;

            List <Policy>    policyList    = new List <Policy>();
            List <Selection> selectionList = new List <Selection>();
            Selection        selection     = new Selection();

            selection.DisplayName = environmentProperty.Value;
            selection.Name        = environmentProperty.Value;
            selectionList.Add(selection);
            policyList.Add(new AvailableSelectionsPolicy(selectionList, false));
            newEnvironmentProperty.Policies = policyList;
            composerTemplates.ForEach(template =>
            {
                List <ViewProperty> properties = arg.Properties;
                properties.Add(new ViewProperty()
                {
                    DisplayName = $"{template.DisplayName} ({template.Id})",
                    Name        = template.Id,
                    RawValue    = false,
                    UiType      = "Options"
                });
            });
            context.CommerceContext.AddModel(new MultiStepActionModel(context.GetPolicy <KnownComposerActionsPolicy>().SelectTemplatesToPullFromEnvironment));
            return(arg);
        }