Search code examples
c#asp.net.netentity-frameworkodata

moving property to anther property in class throws exception "System.InvalidCastException: 'Object must implement IConvertible.'"?


what I am trying to find away to move DynamicProperties property to JSONdata property because of that I have this reflection function to do the job when it came to DynamicProperties it throws exception "System.InvalidCastException: 'Object must implement IConvertible.'" can someone help me?

    public IHttpActionResult Get(ODataQueryOptions<Client> options)
    {
         if(queryNew.ElementType == typeof(Client)){}
        else //if (queryNew.ElementType.Name == "SelectSome`1")
        {
            var results = new List<Client>();
            try
            {
                foreach (var item in queryNew)
                {
                    var dict = ((ISelectExpandWrapper)item).ToDictionary();
                    var model = DictionaryToObject<Client>(dict);
                    results.Add(model);

                }

                return Ok(results);
            }
            catch (Exception)
            {

                throw;
            }
}

    private static T DictionaryToObject<T>(IDictionary<string, object> dict) where T : new()
    {
        T t = new T();
        PropertyInfo[] properties = t.GetType().GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (!dict.Any(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase)))
                continue;
            KeyValuePair<string, object> item = dict.First(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase));
            Type tPropertyType = t.GetType().GetProperty(property.Name).PropertyType;
            Type newT = Nullable.GetUnderlyingType(tPropertyType) ?? tPropertyType;
            if(dict.Any(x => x.Key.Equals("DynamicProperties", StringComparison.InvariantCultureIgnoreCase)))
            {
                object temp = JsonConvert.SerializeObject(item.Value, Formatting.Indented); //Convert.ChangeType(item.Value.ToString(), newT);
                t.GetType().GetProperty("JsonData").SetValue(t, temp, null);
            }
            object newA = Convert.ChangeType(item.Value, newT);
            t.GetType().GetProperty(property.Name).SetValue(t, newA, null);
        }
        return t;
    }

client class

public class Client
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string ParticipantId { get; set; }
    public DateTime? BirthDate { get; set; }
    public int Gender { get; set; }
    public byte? Age { get; set; }
    public int Status { get; set; }
    public string Notes { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? UpdatedDate { get; set; }
    public DateTime? DeletedDate { get; set; }
    public bool IsDeleted { get; set; }
    public int? DefaultLanguageId { get; set; }
    public Guid UserId { get; set; }
    public string JsonData { get; set; }

    public virtual ICollection<ClientTag> ClientTags { get; private set; }

    protected IDictionary<string, object> _dynamicProperties;
    public IDictionary<string, object> DynamicProperties
    {
        get
        {
            if (_dynamicProperties == null)
            {
                if (this.JsonData == null)
                {
                    _dynamicProperties = new Dictionary<string, object>();
                }
                else
                {
                    _dynamicProperties = Mapper.Map<IDictionary<string, object>>(JObject.Parse(this.JsonData));
                }

                //_dynamicProperties.Source.ListChanged += (sender, e) => { this.AssessmentData = _dynamicProperties.Source.ToString(); };
            }

            return _dynamicProperties;
        }
    }
    public void UpdateJsonDataFromDynamicProperties()
    {
        this.JsonData = Mapper.Map<JObject>(_dynamicProperties).ToString();
    }
}

Solution

  • When you get an IConvertable error, that means that you have tried to assign one type to another. for example, if you try to assign textbox to string, you will get an error because you cannot assign object to string, you will have to use Iconvertible. e.g.:

    String.ToString();
    

    Which implicitly implements Iconvertible.

    I cannot tell exactly where your code fails, you didn't mention it either, I can just tell you that somewhere in the client methods, you are trying to assign two different types and you just cannot do that.

    Use debug on both the server and client class and check where you are trying to assign two different types, then implement the desired Iconvertible, meaning make the needed conversion.

    The only problem in your code here, is that you are trying to assign to different types.

    My guess, is that this line caused trouble:

     if (this.JsonData == null)
                    {
                        _dynamicProperties = new Dictionary<string, object>();
                    }
                    else
                    {
                        _dynamicProperties = Mapper.Map<IDictionary<string, object>>(JObject.Parse(this.JsonData));
                    }
    

    When you are trying to assign _dynamicProperties into a dictionary object when in fact you declared _dynamicProperties as IDictionary object.

    There is a subtle different between Idictionary and dictionary object, they are not of the same type. this is the change need to be done:

     if (this.JsonData == null)
                        {
                            _dynamicProperties = new IDictionary<string, object>();
                        }
                        else
                        {
                            _dynamicProperties = Mapper.Map<IDictionary<string, object>>(JObject.Parse(this.JsonData));
                        }