we are developing mobile applications with Xamarin on the top of CUBA backend and were unable to find any ready solutions to work with CUBA REST API within C#. So we decided to implement our own solution and believe it could be useful for other developers as well.
We are going to open source the code of the library in the nearest future. The core developer of the library is fellow @Zidar, please don’t hesitate to ask questions.
At the moment the library has the following functionality:
Authentication using access and refresh tokens
Code generation for entites using Metadata
Also we have plans to implement a sort of an entity buffer to address the requirement to support offline-mode (surely this will have some constraints to preserve consistency and so on).
This sounds great Ilia! It’s good to see that there are others that have a similar requirement.
I have actually toyed with idea but stopped as I feel there is one critical piece missing from the CUBA REST interface and that us the ability to generate Swagger for the Domain Model. I understand this has been scheduled in the next release based on YouTrack PL-9387. You may want to hold off with your initiative until PL-9387 has been finished to see if it meets some of your requirements.
This was my discussion about a similar requirement but coming from a different angle.
What I would want, at least for a C#/Xamarin project is the ability to generate strongly typed proxies so that we get Intellisense from DTO’s that reflect the model and services defined in CUBA. I use both Visual Studio for
Xamarin dev and Android Studio + other tools and as such and was looking at CodeGen as my initial go to. I have not used CodeGen and as with most proxy generators, they usually have limitations but at least of body of work has been done. CodeGen does have a pluggable generators and there are 2 implementations for C# as shown in the Swagger Editor below:
I spent years doing offline interfacing to SAP using IDocs and while this was on a much larger scale, the same techniques/issues apply at least for what I will call Unattended Offline.
Unattended Offline is hard to do generically as there are a usually many of domain specific issues with the consistency or techniques for eventual consistency of transactions. Offline requires guaranteed delivery (Queuing), once and only once processing (Correlation) + a mechanism to notify of and process exceptions after the fact.
There is a whole other discussion for what I call Attended Offline or simply, user initiated data sync which is much easier to implement.
What type of Offline are you are thinking of? I suspect that you are just thinking of just of mobile devices?
As Ian mentioned in the post above, Swagger is a tool anyone will be able to use to generate a model since CUBA v 6.9. But once the code generated the model still evolves. Our library provides an easy way to check an existence model against the server one to find changes, which we’ve found quite usefull.
You can find more details in README.md files in repositories.
Any feedback and comments would be appreciated.
As to Offline-mode we are going to implement. Going by the preliminary analysis it looks as if we just need to have a kind of the entity buffer to be able to work with a set of entities while the a mobile device is offline. But everything depends on what does this “work” mean? At the moment it’s for sure that user should be able to:
edit some entities
attach images (formally speaking it sounds like entity creation)
Of course we should consider to provide a pluggable architecture for different eventual consistency strategies to be utilized in various domain realms/particular entites when device goes online and a syncronization tooks place.
Awesome work, I will take a more in depth look later this week.
I just want to clarify that the Swagger code generation tool comes in both a cli (like your CubaRest.CodeGenerator) app and web editor. I intended on using the cli version in a MSBuild task to generate the domain model as part of the build process. This would mean that the domain model in CUBA and client would always be in sync.
Here are a couple of observations:
The Swagger tools have not been updated since 2016 but then, many tools once developed don’t change.
Using a Java cli from MSBuild is not optimum as you have to parse the output for errors.
It would not take much work to make a MSBuild task to wrap your CodeGenerator and generate the code as part of the build process.
Your api needs to support async/await by default as this is “modern” way of doing a .Net api. Synchronous operations are blocking versions of the asynchronous api. Your example shows you wrapping a sync operation with a task and I don’t think this is right. It should look like “var result = await api.ListEntities<YourEntityType>();”. My intention is not to do a code review but rather point you to current conventions.
It’s clear you are Java developers in the .Net world. It’s much like seeing .Net developers in the Java world. The respective conventions don’t align and It becomes apparent when you build a fully fledged application utilizing multiple libraries.
The one question I have is, how do you do things like querying, limiting and paging data? I did a quick peruse of the code and I did not see any facilities for handling this. I realize this is the first cut, but on a mobile device, this is going to be my first requirement.
I am not sure if you took at the generated code from the Swagger generation tool for csharp, but there is some good concepts in their api especially with how they handle sync/async/await/limiting/paging/queries/data types such as byte arrays, datetime, time etc and extra bonus they use RestSharp as well!
Right now it is a very early version. Certainly it will be developed further.
Async/await inside lib are coming soon.
For limiting and paginating features take a look at EntityListAttributes class. ListEntities() uses query attributes as an optional parameter.
Create/update/delete oprations are coming soon eigther - as soon as I need them in main app, being developed now.
I think you are using RestSharp as an example of how to model sync/async a .Net api is probably not best example because of it’s history. This is because RestSharp started many years ago and the first versions used Microsoft’s http client which was geared towards sync operations … yes it did async but it did not work well and hence why everyone wrote their own. This is why RestSharp does sync first and then wraps the sync operations in a task to make them async.
In my experience, the more modern api’s all do async first and may not even have a sync api. If you want a sync operation, it’s as simple as using .Result or .Wait(). Note that the linked article is old and some of the issues they talk about are no longer an issue with newer versions of C#.
The one other thing I think would be nice is for the api to support dynamic as well strongly typed objects. I don’t believe Java has a dynamic data type.
Many of the .Net Micro ORM’s support serialization either to a dynamic data type or DTO/POCO. Using the dynamic data type does not require a code generator and while now losely/duck typed, for many applications this is “good enough”.
It would be great to be able to deserialize a response into a DTO/POCO or dynamic object.
One last observation, using attributes for paging/limiting is too limiting as you have now configured the api statically using code. I would want to be able to configure these parameters externally, possible from a config setting??? You will also notice in .Net that people are careful when using reflection as it’s expensive especially on a mobile device as it affects battery life. IMO, try stay away from reflection if possible.
You guys have done some good work here, please take my feedback/suggestions as constructive.
Hi Ilia, are you still on the project? how the library is going? we are preparing a cuba/xamarin app … os we would like to use the library too, but we cannot find a documentation… i mean, we tryd to read the comment but since they are in, i think, Russian, it’s really not easy to understand how the logic is going… can you give an input? thank you very much
That’s a great notice!!! you guys are doing a really great work!
So about the library, i installed the restsharp nuget and now? i mean, do i have only to import some class or all the project?
Because of the, i think it’s Russian language of the comment, i cannot follow the logic of the entire library… can you explain a little bit which is the logic? i mean, what do we have to do and use the library?
thank you very much, and again, awsome work.
This should be enough to send simple requests to Cuba.
While you don’t have your Cuba Entitiy types system, you can make requests translated into Dictionary like this:
var result = api.ListEntities(“cuba$EntityType”);
As for CodeGenerator, rename ProjectConfiguration_Template.json and RestApiConnection_Template.json to ProjectConfiguration.json and RestApiConnection.json respectively. Adjust server url/username/password. Launch the app. It will create files with Cuba entity types in /bin/Debug/Model folder. Copy that files to your project.
Hi all, here we go… I added cubarest libraries on my project, put two entries and a button to fire the connection and see what happen… i just wanted to contact the cuba demo dashboard … but when i click the button, everything is ok but the response = client.Execute(request); command fire an error on the application This nonCLS method is not implemented … and in the ide a popup exit saying system.reflection.targetinvocationException has been thrown…
OK, thanks Sergey, i will investigate about the error. Anyway, creating the signed apk, installing it directly on the same device is no longer getting the error… i think it is a visual studio live debugger issue…
Well, so, now i reach a CUBA platform, how i could user the crud operation of the library? do i have to create local entities ( the same i have on cuba) or i can just connect and send crud operations?
thank you very much, and again: great work with the library…
Hi Sergey, thank you for your response. I already have my cuba server entities ready so i can start work with them… so, i have a question: how do you manage the token and refresh token?
i mean, the logic we want to use is: Firstly we request the token and then if a service goes in token expired error we send the refresh token to continue with the process and get rid of the token expired error…