Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with $expand when the Model have loops between object types #2

Open
legacy-carlostorrao opened this issue Jun 11, 2013 · 1 comment
Assignees
Labels

Comments

@legacy-carlostorrao
Copy link

Hi, first of all, thank you a lot for this great toolkit.

Right now, i'm having a trouble using $expand property from the OData protocol when using an expand in a Object which have other property object which have a List<> of the first Object (loop of object references).

My model is something like:

public class Content
{
public string Id { get; set; }
public string Title { get; set; }
public Channel Channel { get; set; }
}

public class Channel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IList<Content> Contents { get; set; }
}

And i invoke something like: "http://localhost/OData.svc/Contents?$expand=Channel&$select=Id,Channel"

I already identified the problem in the "Microsoft.Data.Services.Toolkit.QueryModel.TypeExtensions" class, and made the following changes.

public static IDictionary GetPropertyDetails(this IEnumerable properties, Type type) { var projectedProperties = new Dictionary(); var projectedTypes = new List() { type }; Action, Func> processProperties = null; processProperties = delegate(IEnumerable propertyList, Func accessor) { if (accessor == null) accessor = o => o;
            foreach (var property in propertyList)
            {
                var local = property;
                if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                {
                    var propertyDetails = new PropertyDetails
                                              {
                                                  PropertyInfo = local,
                                                  PropertySetter = (target, value) => local.SetValue(accessor(target), Convert.ChangeType(value, local.PropertyType.TypeOrElementType()), null)
                                              };

                    projectedProperties.Add(local.GetUnderlyingColumnName(), propertyDetails);
                }
                else if (property.PropertyType.IsArray)
                {
                    var propertyDetails = new PropertyDetails
                    {
                        PropertyInfo = local,
                        PropertySetter = (target, value) => local.SetValue(accessor(target), value, null)
                    };

                    projectedProperties.Add(local.GetUnderlyingColumnName(), propertyDetails);
                }
                else
                {
                    if (!projectedTypes.Contains(local.PropertyType))
                    {
                        projectedTypes.Add(local.PropertyType);
                        processProperties(local.PropertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance), o => local.GetValue(accessor(o), null));
                    }
                }
            }
        };

        processProperties(properties, null);
        return projectedProperties;
    }

Basically I added a list of types already iterated to avoid a loop in recursion of the processProperties(...) method! That way, it works just fine. Otherwise, it occurs an Exception in the Dictionary repeated key, and if you do an if before to check if it contains that key, occurs a StackOverflow because of the loop recursion problem.

Do you confirm that this is a bug, or am I doing something wrong?

@oising
Copy link
Owner

oising commented Jun 11, 2013

Sounds like a bug to me - I'll try to repro. Thanks!

@ghost ghost assigned oising Jun 11, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants