jaydata icon indicating copy to clipboard operation
jaydata copied to clipboard

OData entity with array property of complex types only ever contains one element

Open oising opened this issue 13 years ago • 8 comments

My OData service returns an entity with an array property of complex types. The JSON returned has been validated and confirmed to contain THREE complex types in the array. When accessing the entity instance in script, the array contains ONE element only. I'm working with 1.2.6

oising avatar Jan 03 '13 21:01 oising

I can also see that when I examine initData in the single element, the properties exist but their values are undefined.

oising avatar Jan 03 '13 21:01 oising

ok, so I fixed this partially by adding a "fromDb" converter in the odata provider.

oising avatar Jan 04 '13 22:01 oising

Please can you submit a metadata definition as seen by jaydata? So could you just get it with JaySvcUtil and submit? This use case has a number of unit tests in the system, so it should really work (albeit we could not test it with WCF only with JayStorm) Peter

From: oising [mailto:[email protected]] Sent: Thursday, January 3, 2013 10:01 PM To: jaydata/jaydata Subject: [jaydata] OData entity with array property of complex types only ever contains one element (#72)

My OData service returns an entity with an array property of complex types. The JSON returned has been validated and confirmed to contain THREE complex types in the array. When accessing the entity instance in script, the array contains ONE element only. I'm working with 1.2.6

— Reply to this email directly or view it on GitHubhttps://github.com/jaydata/jaydata/issues/72.

PeterAronZentai avatar Jan 07 '13 11:01 PeterAronZentai

I'll try to put something together this week for you Peter, thanks. However I'm sad to say after two months of working on the bleeding edge with JayData, I've taken the decision to drop it entirely and take the hit of rebuilding with a pure datajs foundation. I keep hitting too many bugs and at three weeks over schedule, I can't afford to hit any more. At this point I'd have to drop all navigational properties and all complex type properties from my entities in order to use your library, and if I do that, there is little benefit for me to stick with it. I'll revisit it for the next project.

oising avatar Jan 08 '13 01:01 oising

Hi Peter,

I looked again, and I don't see how this could be working in the OData provider. I know you did some work with the sqLite provider, but OData is non-functional in this regard. Here's the modifications I made in order for it to work (Oh, first I had to add $data.Array to the list of "supportedDataTypes" in the provider - it was missing - I figured this out from looking at the sqLite mods you did):

    fieldConverter: {
        value: {
            fromDb: {
                '$data.Integer': function (number) { return (typeof number === 'string' && /^\d+$/.test(number)) ? parseInt(number) : number; },
                '$data.Number': function (number) { return number; },
                '$data.Date': function (dbData) {
                    // FIX: odata v3
                    if (dbData && dbData.constructor === Date) {
                        return dbData;
                    }
                    return dbData ? new Date(parseInt(dbData.substr(6))) : dbData;
                },
                '$data.String': function (text) { return text; },
                '$data.Boolean': function (bool) { return bool; },
                '$data.Blob': function (blob) { return blob; },
                '$data.Object': function (o) { if (o === undefined) { return new $data.Object(); } else if (typeof o === 'string') { return JSON.parse(o); } return o; },
                '$data.Array': function (o) {
                    if (o === undefined) {
                        return new $data.Array();
                    } else if (o instanceof $data.Array) {
                        return o;
                    }

                    // FIX: odata v3 collection of complex types
                    if (o.__metadata && o.__metadata.type) {
                        var type = o.__metadata.type;
                        var re = /^Collection\(([^\)]+)\)$/;
                        if (re.test(type)) {
                            var typeName = re.exec(type)[1];
                            console.log("Building collection of " + typeName);
                            var propValue = new $data.Array(o.results.length);
                            for (i=0; i < o.results.length; i++) {
                                propValue[i] = new $data.Class.classNames[typeName] ( o.results[i] );
                            }
                            return propValue; //
                        }
                    }

                    // not much point in parsing things other than strings, right?
                    if ((typeof o === "string") || o instanceof String) {
                        return JSON.parse(o);
                    }

                    console.log("Unable to deserialize.");
                    console.log(o);
                    return o;               
                },
                '$data.Geography': function (geo) {
                    if (geo && typeof geo === 'object' && Array.isArray(geo.coordinates)) {
                        return new $data.Geography(geo.coordinates[0], geo.coordinates[1]);
                    }
                    return geo;
                },
                '$data.Guid': function (guid) { return guid ? new $data.Guid(guid) : guid; }
            },

Anyway, I hope this helps. My journey wasn't completely wasted as I leveled up my own javascript so much while debugging your stuff that I felt comfortable dropping it entirely and just layering directly on datajs. Frankly, I think this is where your audience is right now anyway - for RAD work by people eager to get a linq/C# experience. I look forward to watching jaydata grow, albeit from a further distance than before. Thanks again for all your help.

oising avatar Jan 09 '13 14:01 oising

Oh, and I'm forcing verbose JSON with an accept header too, as JSON light is the new standard for v3 as you know.

oising avatar Jan 09 '13 14:01 oising

Hello Oisin,

Thanks for that extension and the fix.

To help at least understand while certain things work with the OData provider and others don’t there is a very simple rule of thumb: OData features that are conceivable with WCF/EF combo has unit tests executing against an actually working implementation. Other things are tested against standard specs – as the closest effort. Also it’s a growing experience for us getting the OData V3 features start working over WCF Data Services/EF. The picture is now even more detailed as certain V3 things are only conceivable with ASP.NET WebAPI OData but not with WCF Data Services – so we now started working with the WebAPI stack too. Your OData implementation was/is not accessible for us, so we could not try “peculiar things”. Most of the time an actually working server implementation is what we lack in order to fix things. Any time in the future or in the present: if you provide a CORS accessible endpoint of your API we can just chain it into our unit tests – one stone and at least 2.5 birds as we can have your issues fixed in ours (since we don’t have to try to simulate the server) and also it makes identifying braking changes easier. Having a jsfiddle pinpointing your issue or bug you encountered is also a very efficient way and lets us fix the issue in hours instead of days – the repro usually takes 5times the effort then the fix. So think this over – we are 100% in the time work on OData V3 things now – so we can allocate time on saving your project deadline and we are really eager to help.

About the complex type:

Complex types as properties do work with the current OData provider – albeit with a glitch in change propagation. You have to reassign the whole complex property if a member of is it changed (entity does not get dirtied otherwise) this one gets fixed with 1.2.7

Array<ComplexType>: This is thing is experimental and in JayDat 1.3 will have the majority of the OData V3 support in a good shape. Sorry – I do hope we did not raise false expectations on that. BTW: the OData provider in JayData handles array complex props with the model binder (not fromdb/todb mapping) – that is why you did not find it. However I only found unit tests towards the XML output and the only tested environment was JayStorm as server and .NET C# as client.

Best Peter

PeterAronZentai avatar Jan 09 '13 14:01 PeterAronZentai

Thanks for the update Peter.

I'm not sure if this helps you much, but ASP.NET Web API and WCF Data Sevices stacks are based on the same underlying ODataLib now. If you're looking at this stuff closer, I strongly suggest you use the current version 5.2 which is available on NuGet for building against (e.g. runtime), and there's also a "tooling update" which updates all of the templates in VS so you have parity at design time too. This is available here:

http://blogs.msdn.com/b/astoriateam/archive/2012/12/17/wcf-data-services-5-2-0-released.aspx

The reason I suggest 5.2 is because there are a lot of critical changes around OData v3, including using JSON light as the default. There are other improvements there too, too long to detail here.

To be brutally honest Peter, I can't go back to JayData at this point - it's a done deal. It's not your fault, I was just flying too close to the sun on this one. I really leveled up my javascript a lot in the last two months and working with datajs directly is just ... safer... at this point for my project. TypeScript is helping a lot too. I will continue to stay involved as best I can and will likely return to jaydata for some personal work in the near future.

oising avatar Jan 09 '13 15:01 oising