Retrieving the Customer Attributes by Customer Id ?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
9 years ago
We are storing some customer metadata (as CutomerAttributes).

I've been digging in and was looking to see where I can access those properties when I have _workContext.CurrentCustomer - the services calls seem to be for pulling all the attributes, whereas I'm just wanting the attributes for the current customer.

I see the 'CustomerAttributeService'  and methods such as 'GetCustomerAttributeById' but these are the attribute id's not the CustomerId correct ?

I would want to be able to say 'get me this attribute value by id and by the current customer'

Thanks
9 years ago
Customer attribute is not depends on  customer id, once you create a customer attribute it is applied to all customer. So it does not make any sense 'Customer Attributes by Customer Id '
9 years ago
Not sure why you say this.

ie. I created a customer attribute (via admin panel) - that form and value show up on the register.   So it is storing it 'per customer'  - so it makes sense to want to be able to get those values.

It's stored as a string, and I can get it via this:

var selectedCustomerAttributes = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CustomCustomerAttributes, _genericAttributeService);
                var customerAttributes = _customerAttributeParser.ParseCustomerAttributes(selectedCustomerAttributes);
                var customerValues = _customerAttributeParser.ParseCustomerAttributeValues(selectedCustomerAttributes);

however, I'm not sure about the best way to do this.
9 years ago
So, I presume are looking for attribute values for specific customer, like you have a attribute 'Favorite color', for customer  1 it's Red, for customer 2 it's Green.

You are looking for a method like GetCustomerAttributeValue(customerId, attributeId), it's not that straight forward. You can research on the CustomerController -> PrepareCustomerInfoModel ->  #region Custom customer attributes

Hints
1. First get all attributes for a specific customer
  string selectedCustomerAttributes = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CustomCustomerAttributes, _genericAttributeService);


2. Parse the attributes
 var enteredText = _customerAttributeParser.ParseCustomerAttributeValues(selectedCustomerAttributes);


3. For textbox
 return enteredText[0]


You can handle other controls too
9 years ago
that code does not work properly.

have a try at it - go create a textbox property ie. favorite dog name and then a list property, etc... you'll find it fails to capture all the key and values (which is what it should be returning imo) for the customer
9 years ago
This isn't code complete, but here is a start:


public virtual IDictionary<string, object> ParseCustomerCustomAttribute(string attributes)
        {
            var caValues = new Dictionary<string, object>();
            var caCollection = ParseCustomerAttributes(attributes);
            foreach (var ca in caCollection)
            {
                var caValuesStr = ParseValues(attributes, ca.Id);

                if ((ca.AttributeControlType == AttributeControlType.TextBox ||
                    ca.AttributeControlType == AttributeControlType.MultilineTextbox ||
                    ca.AttributeControlType == AttributeControlType.Datepicker ||
                    ca.AttributeControlType == AttributeControlType.FileUpload) && caValuesStr.Any())
                {                    
                    caValues.Add(ca.Name, caValuesStr.First());
                }
                else
                {
                    var multipleValues = new List<CustomerAttributeValue>();
                    foreach (string caValueStr in caValuesStr)
                    {
                        if (!String.IsNullOrEmpty(caValueStr))
                        {
                            var caValueId = 0;
                            if (int.TryParse(caValueStr, out caValueId))
                            {
                                var caValue = _customerAttributeService.GetCustomerAttributeValueById(caValueId);
                                if (caValue != null)
                                {
                                    multipleValues.Add(caValue);
                                }
                            }
                        }
                    }
                    if (multipleValues.Any())
                    {
                        caValues.Add(ca.Name, multipleValues);
                    }
                }
            }
            return caValues;
        }
9 years ago
For what it's worth, this is the helper class that Shipping Director uses support its Custom Customer Attribute Extensions:
    GetAttributeValues(this Customer customer, string attributeName, string valueSeparator)
    GetAttributeValues(this Customer customer, string attributeName)
    HasAttributeValue(this Customer customer, string attributeName, string valueName)
    HasAttributeValue(this Customer customer, string attributeName)
    HasAttributeValue(this Customer customer, int valueId)


-It's in an Extension class, so it uses Resolve<ICustomerAttributeService> rather than the DI'd service.

-Internally, it uses a helper class (rather than Dictionary like yours), so that it also has the Value Id.  (Because value text might be localized, or store owner might change the text - the attribute Id never changes.)
        // helper class
        private class AttributeValuePair
        {
            public string AttributeName { get; set; }
            public int ValueId { get; set; }
            public string ValueText { get; set; }
        }

-I decided to do my own XDocument.Parse  ( I forget why, but I think because the core Parse did not look optimal for my purpose)

        private static IList<AttributeValuePair> GetSelectedAttributes(Customer customer)
        {
            if (customer == null)
                return null;

            string selectedCustomerAttributes = customer.GetAttribute<string>(SystemCustomerAttributeNames.CustomCustomerAttributes);

            var attributeValueList = new List<AttributeValuePair>();

            if (String.IsNullOrWhiteSpace(selectedCustomerAttributes))
                return attributeValueList;

            var _customerAttributeService = Nop.Core.Infrastructure.EngineContext.Current.Resolve<Nop.Services.Customers.ICustomerAttributeService>();
            var customerAttributes = _customerAttributeService.GetAllCustomerAttributes();

            XDocument doc = XDocument.Parse(selectedCustomerAttributes);

            var selectedAttributes = doc.Root.Descendants("CustomerAttribute");
            foreach (var selectedAttribute in selectedAttributes)
            {
                int selectedId = int.Parse(selectedAttribute.Attributes("ID").First().Value);
                foreach (var value in selectedAttribute.Descendants("CustomerAttributeValue").Elements("Value"))
                {
                    var customerAttribute = customerAttributes.Single(pva => pva.Id == selectedId);
                    switch (customerAttribute.AttributeControlType)
                    {
                        case AttributeControlType.DropdownList:
                        case AttributeControlType.RadioList:
                        case AttributeControlType.Checkboxes:
                            var productVariantAttributeValue = customerAttribute.CustomerAttributeValues.Single(pvav => pvav.Id == int.Parse(value.Value));
                            var attributeValue = new AttributeValuePair()
                            {
                                AttributeName = customerAttribute.Name,
                                ValueId = productVariantAttributeValue.Id,
                                ValueText = productVariantAttributeValue.Name
                            };
                            attributeValueList.Add(attributeValue);
                            break;
                        default:
                            attributeValue = new AttributeValuePair()
                            {
                                AttributeName = customerAttribute.Name,
                                ValueId = 0,
                                ValueText = value.Value
                            };
                            attributeValueList.Add(attributeValue);
                            break;
                    }
                }
            }

            return attributeValueList;
        }
9 years ago
looks good - I'll give it a shot - thanks!
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.