So Delphi has the ODATA dispatcher instead of the REST dispatcher in .NET but basically the two do the same thing? If so, howcome the same functionality was implemented differently between the two platforms?
I’m experimenting with the ODATA now, have managed to retrieve records in JSON format (the clientid header trick from the other topic worked for authentication) but having some strange null conversion errors when trying to do a PUT update right now. I’ll continue to experiment.
Yeah I’m following the same pattern but I can’t work out how the PUT works to update a record - if I omit some columns then it complains they’re required, although this seems to have no correlation with which columns in the database are required and, if I put all the fields into the body then it comes up with a null conversion error.
I think I’ll spin up a small dedicated test app first using the wizard and get that working.
This works fine. Company is a single table from my database which has an integer primary key so this returns the columns for the record with ID=1.
If I supply the JSON returned from this as the body to a PUT with the same URL, I get this error:
“Cannot find item “dbo_Company” in collection of type TDAServerDatasetCollection”
If I trap the OnProcessTargetUrl event, I notice both the TargetUrl and TableName have “dbo_Company(1)” in them, is that correct or should it just be the table name? If I remove the (1) from the URL so it’s just:
Ok, it works in an isolated test project but I get the conversion exception error when I try it in my main app.
Turns out it’s the business processor logic during the update. I’m using strongly-typed classes and it turns out the Old… values appear to be NULL. So I have some logic running that checks if the update is altering the Name column, i.e. “if OldName <> Name then…” and this is throwing an exception.
Is this correct behaviour? In other words, when using OData, will the “old” values in the delta be unavailable?
Ok so, when using JSON, the old values aren’t available. Guess that makes sense as, with my regular Delphi client, it’s the TDAMemDataTable that tracks changes in the delta and then sends it, complete with the old values, to the server. Obviously the old values aren’t supplied as part of the JSON payload.
It did occur to me how deletes work as, in this case, the primary key is held in the Old values, OldId in my case, but this value does appear to be present so I can use it for deletes.
It is a bit of a pain as some of my business logic depends on knowing what columns have actually changed, as described above, and I can’t do this if the old values aren’t present.
(Just seen your update about the streamer, I’ll try that but the rest of this was written before that)
So basically, when updating via a PUT, the JSON body only needs to contain the values I want to change, so the presence of the value indicates that it’s being updated. I can alter my business logic to cater for that.
One quick question though. Many of my business logic processors update the modified date to the current server time as part of the BeforeProcessChange handler, thus ensuring it’s always modified. If the client didn’t supply this column as part of the JSON then the value isn’t present so I can’t just do “ModifiedDate := Now” in my code. Is there a way I can set/add a column which wasn’t supplied?
you can do it manually in DAService events like OnBeforeProcessDeltas
create BP.OnBeforeProcessChange event and assign Now to required field. this event should be assigned to specific BP in the DAService.OnBusinessProcessorAutoCreated event
Regards the streamer, I’m not entirely sure how these work. I just use a Bin2DataStreamer for all my services and it works fine so I left it alone. As this is a binary protocol, I presumed it was only used for communication from my Delphi client and that any “text based” client such as XML/JSON/REST/ODATA/etc would use something else.
Like I said, I’m not really sure how streamers work or how they affect things. I tried swapping the Bin2 for a JSON one as an experiment but functionality was identical for the ODATA calls.
This is basically what I’m doing now - I have design-time BP components with OnBeforeProcessChange handlers. In these I update modified date values and also sometimes change other values in response to user changes. The problem is that, if these values weren’t supplied as part of the JSON body in the PUT call then the corresponding strongly-typed class properties don’t work, so I can’t just do “ModifiedDate := Now” or whatever.
Inside these handlers, how can I change these values?
Ok I understand what you mean but, if I’m honest, I really dislike that.
My current solution is nice and elegant. Within each BP’s BeforeProcessChange handler I can not only do validation but also set or change any field value before the change is committed to the database, including fields not set by the client, all using the robust, strongly-typed class properties.
Giving that up in favour of messing about with the deltas in the service handler just to get ODATA working isn’t something I really want to do to be honest.
another solution: you can modify user’s request in HTTPServer.OnCustomResponseEvent event and add missing ModifiedDate field to request body and pass request to OData dispatcher.