SkywardApps/popcorn

Blind Expansion only applies to primary objects, not properties on objects

Closed this issue · 2 comments

Currently it would seem that blind expansions aren't universally applied to objects. In the example below you will see that if an API response is the object itself it is expanded blindly, but that same object, used as a property, on a different object in a response is not expanded or allowed to be manipulated by includes.

Steps to Reproduce

In the example project you'll see we have a Business class and an API endpoint to GET businesses.

    public class Business
    {
        public string Name { get; set; }
        public string StreetAddress { get; set; }
        public int ZipCode { get; set; }
        
        public List<Employee> Employees { get; set; }

        public enum Purposes
        {
            Shoes,
            Vehicles,
            Clothes,
            Tools
        }
        public Purposes Purpose { get; set; }
    }

If the GET businesses endpoint is queried as below you will see that that it returns an expanded response as you'd expect:

http://localhost:49699/api/example/businesses?include=[Name,ZipCode,StreetAddress,Employees]

{
    "Success": true,
    "Data": [
        {
            "Name": "Shoe Biz",
            "ZipCode": 55555,
            "StreetAddress": "1234 Street St",
            "Employees": [
                {
                    "FirstName": "Jack",
                    "LastName": "Donaghy",
                    "Employment": "Employed"
                },
                {
                    "FirstName": "Liz",
                    "LastName": "Lemon",
                    "Employment": "Employed"
                }
            ]
        },
        {
            "Name": "Car Biz",
            "ZipCode": 44444,
            "StreetAddress": "4321 Avenue Ave",
            "Employees": []
        }
    ]
}

however
You'll see in code that I'm pushing soon (or that you can recreate yourself) if we add a "Manufacturer" property to our Cars class as shown below.

    public class Car
    {
      ......

        public Business Manufacturer { get; set; }
    }

    public class CarProjection
    {
       .....

        public Business Manufacturer { get; set; }
    }

And a request is made to the GET cars endpoint:

http://localhost:49699/api/example/cars?include=[Make,Model,Manufacturer]

{
    "Success": true,
    "Data": [
        {
            "Model": "Firebird",
            "Make": "Pontiac",
            "Insured": false
        },
        {
            "Model": "250 GTO",
            "Make": "Ferrari N.V.",
            "Insured": false,
            "Manufacturer": {
                "Name": "Car Biz",
                "StreetAddress": "4321 Avenue Ave",
                "ZipCode": 44444,
                "Employees": [],
                "Purpose": 1
            }
        },
        {
            "Model": "Cayman",
            "Make": "Porsche",
            "Insured": false,
            "Manufacturer": {
                "Name": "Car Biz",
                "StreetAddress": "4321 Avenue Ave",
                "ZipCode": 44444,
                "Employees": [],
                "Purpose": 1
            }
        }
    ]
}

Should we attempt to do any specific includes on the manufacturer property we don't see any change in results:

http://localhost:49699/api/example/cars?include=[Make,Model,Manufacturer[Name]]

{
    "Success": true,
    "Data": [
        {
            "Model": "Firebird",
            "Make": "Pontiac",
            "Insured": false
        },
        {
            "Model": "250 GTO",
            "Make": "Ferrari N.V.",
            "Insured": false,
            "Manufacturer": {
                "Name": "Car Biz",
                "StreetAddress": "4321 Avenue Ave",
                "ZipCode": 44444,
                "Employees": [],
                "Purpose": 1
            }
        },
        {
            "Model": "Cayman",
            "Make": "Porsche",
            "Insured": false,
            "Manufacturer": {
                "Name": "Car Biz",
                "StreetAddress": "4321 Avenue Ave",
                "ZipCode": 44444,
                "Employees": [],
                "Purpose": 1
            }
        }
    ]
}

Expected Behavior

I would potentially expect the object to be blindly expanded universally, whether as a response object itself or when referenced as a property.

Possible Implementation

We could probably refactor the logic a bit to broaden the scope of when objects are checked to blind expand and how. Currently we see the manufacturer is set in the TrySetValue method because there is no mapping to push this logic down the lane and have the object attempt to blindly mapped.

Note: Depending on our implementation here we may also want to consider the impact on the InternalOnly property as it is set on the non-projected object and how that plays in with blind expansion

While this kind of smells like it could be a bug to me, I'm marking as dicussion for now until we get some more input

@undiwahn - do you think we can open this one up for work too?