user351479
user351479

Reputation: 253

Automapper map Dictionary<string, string> and List<string> properties to view model

I have the following view model

public class PlanDetail
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        [DisplayFormat(DataFormatString = "{0:$#.##}")]
        public decimal Price { get; set; }

        public string FrequencyAbbreviatedName { get; set; }

        [Display(Name = "Frequency")]
        public string FrequencyName { get; set; }


        [Display(Name = "Events")]
        public int EventLimit { get; set; }

        [Display(Name = "Help Center Access")]
        public bool HelpCenterAccess { get; set; }

        [Display(Name = "Email Support")]
        public bool EmailSupport { get; set; }

        [Display(Name = "Priority Email Support")]
        public bool PriorityEmailSupport { get; set; }

        [Display(Name = "Phone Support")]
        public bool PhoneSupport { get; set; }

        public bool Active { get; set; }

        public string PictureUrl { get; set; }

        public bool BestValue { get; set; }
    }

I am using stripe.com products and prices.

In my mapping profile class, I am able to map to the basic properties (eg Id, Name, Description, Active).

Mapper.Map<Product,PlanDetail>();

I am not sure how to map the Metadata property (Dictionary<string,string>) or the Images property (List <string>) in the stripe product object to some of the PlanDetail properties.

I created the stripe products in my seed class, and added values to the Metadata and Image properties.

  public static async Task SeedStripeAsync(string stripeKey)
        {
            StripeConfiguration.ApiKey = stripeKey;

            var productService = new ProductService();
            var priceService = new PriceService();

            var products = await productService.ListAsync();

            var productsData = System.IO.File.ReadAllText("../Infrastructure/Data/SeedData/stripe_products.json");

            var productPlans = JsonSerializer.Deserialize<List<StripeProductSeed>>(productsData);

            foreach (var item in productPlans)
            {
                if (!products.Any(x=> x.Name.Equals(item.Name, StringComparison.InvariantCultureIgnoreCase)))
                {
                    var productOptions = new ProductCreateOptions
                    {
                        Name = item.Name,
                        Description = item.Description,
                        Active = item.Active,
                        Images = new List<string>(),
                        Metadata = new Dictionary<string, string>()
                    };

                    productOptions.Images.Add(item.PictureUrl);
                    productOptions.Metadata.Add("EventLimit", item.EventLimit.ToString());
                    productOptions.Metadata.Add("HelpCenterAccess", item.HelpCenterAccess.ToString());
                    productOptions.Metadata.Add("EmailSupport", item.EmailSupport.ToString());
                    productOptions.Metadata.Add("PriorityEmailSupport", item.PriorityEmailSupport.ToString());
                    productOptions.Metadata.Add("PhoneSupport", item.PhoneSupport.ToString());
                    productOptions.Metadata.Add("BestValue", item.BestValue.ToString());

                    var newProduct = await productService.CreateAsync(productOptions);

                    var priceOptions = new PriceCreateOptions
                    {
                        UnitAmountDecimal = item.Price,
                        Currency = "usd",
                        Recurring = new PriceRecurringOptions()
                        {
                            Interval = item.Interval,
                            IntervalCount = (long)item.IntervalCount
                        },
                        Product = newProduct.Id
                    };

                    await priceService.CreateAsync(priceOptions);

                }
            }
        }

I would like to map the stripe Product Metadata properties such as EventLimit, HelpCenterAccess, EmailSupport, PriorityEmailSupport, PhoneSupport, and BestValue to their respective counterparts in the PlanDetail view model.

In addition, I would like to map the stripe Product Image property to the PictureUrl property in the PlanDetail view model.

Any ideas or suggestions how to use automapper for theses properties would be much appreciated.

Upvotes: 0

Views: 152

Answers (1)

Gordon Khanh Ng.
Gordon Khanh Ng.

Reputation: 1680

Here's what I assume

// Just demo class
public class StripeProductSeed
    {
        public string PictureUrl { get; set; }
        public int EventLimit { get; set; }
        public bool HelpCenterAccess { get; set; }
        public bool EmailSupport { get; set; }
        public bool PriorityEmailSupport { get; set; }
        public bool PhoneSupport { get; set; }
        public bool BestValue { get; set; }

        public List<string> ExtractImages() => new() { PictureUrl };

        public Dictionary<string, string> ExtractMetaData() => new()
            {
                {nameof(EventLimit), EventLimit.ToString()},
                {nameof(HelpCenterAccess), HelpCenterAccess.ToString()},
                {nameof(EmailSupport), EmailSupport.ToString()},
                {nameof(PriorityEmailSupport), PriorityEmailSupport.ToString()},
                {nameof(PhoneSupport), PhoneSupport.ToString()},
                {nameof(BestValue), BestValue.ToString()}
            };
    }

The map should be:

public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<StripeProductSeed, PlanDetail>()
                .ForMember(dst => dst.Images, x => x.MapFrom(src => src.ExtractImages()))
                .ForMember(dst => dst.Metadata, x => x.MapFrom(src => src.ExtractMetaData()));
        }
    }

Upvotes: 1

Related Questions