You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi Liquid Team,
I've been using Liquid to develop a simple REST based API with SQL Server backend and Service-Bus publisher/subscriber.
Operations were mostly "CRUD-like" with tiny customizations.
Instead of reporting all my findings/suggestions under separate issues, I've combined them first for discussion under this item.
CRUD Controller
While the out-of-the-box controller provides some useful functionality, it's closed for extension or modification, making it hard to use for any custom scenarios, and they can be many:
It's not clear from Liquid design how to decouple database entities from API entities, while Liquid imports AutoMapper it would be useful to see how it could be incorporated into the request pipeline.
Currently the only way I see is to create custom controllers, import AutoMapper and translate to DTOs there.
Repositories
Similarly to generic controller EntityFrameworkRepository is closed for extension too, which makes it impossible to add additional, basic functionality like:
Adding custom repositories is difficult due to the way project dependencies are structured. Repository project has a dependency on Domain, hence Domain cannot explicitly depend on Repository.
The only way that worked for me was decoupling Domain Entities from Domain project and creating custom DomainHandlers project.
Suggestion - Modify templates and provide documentation how custom repositories can be added.
Cloud Agnostic Cartridges
While the idea of cloud-agnostic cartridges is appealing, it should support ability to use vendor specific operations. It might not be beneficial for developers to be ignorant of all the features offered by service they depend on. Currently it seems that design principal is either to go full-liquid or full-custom on cartridges, without ability to extend generic functionality
Service Bus Cartridge
For Service Bus in particular, features that are not available:
service bus sessions
service bus message properties - like setting correlation id. The only properties that can be set are user properties.
error handling / validation of configuration
Due to it's generic nature, a lot of features depend on configuration by convention, without validation or error handling that would make it easier to use #107
For publishing, publisher per entity type is required, making the code more verbose than needed. There's no ability to use underlying service bus client to send JSON/Binary.
When subscribing to a queue, multiple subscribers can be registered, but they are executed by random, there's no orchestration based on type. Hence when 2 subscribers are registered for the same queue, each gets object that was an attempt to deserialize, which causes 1 of the subscribers to always error out.
When processing messages, Liquid doesn't extend the lock on the message in a fashion that service bus processor does (or Azure functions by default in their triggers). Lock timeout is also not a configurable property.
When subscribing to service bus, LiquidWorker didn't work with repositories due to #108
Effort reduction
In general, I didn't notice effort reduction. The liquid version of the API had as much code (commands, handlers) as the generic version. For a simple case where CRUD was accepting filters, custom command, handler, repository and controller had to be created.
Other than CRUD Controller and CRUD Repositories, I'm not sure what other functionality is provided by Core/WebApi/Repo projects, other than swagger and mediatr.
This discussion was converted from issue #112 on August 05, 2022 14:08.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi Liquid Team,
I've been using Liquid to develop a simple REST based API with SQL Server backend and Service-Bus publisher/subscriber.
Operations were mostly "CRUD-like" with tiny customizations.
Instead of reporting all my findings/suggestions under separate issues, I've combined them first for discussion under this item.
CRUD Controller
While the out-of-the-box controller provides some useful functionality, it's closed for extension or modification, making it hard to use for any custom scenarios, and they can be many:
Suggestion - make all methods virtual in
Liquid-Application-Framework/src/Liquid.WebApi.Http.Extensions.Crud/Controllers/GenericCrudController.cs
Line 20 in 8f282ce
DTOs
It's not clear from Liquid design how to decouple database entities from API entities, while Liquid imports AutoMapper it would be useful to see how it could be incorporated into the request pipeline.
Currently the only way I see is to create custom controllers, import AutoMapper and translate to DTOs there.
Repositories
Similarly to generic controller
EntityFrameworkRepository
is closed for extension too, which makes it impossible to add additional, basic functionality like:Suggestion - make all properties protected and methods virtual in: https://github.com/Avanade/Liquid-Application-Framework/blob/8f282ceadc79dcf4b3f0f96b3aabe61c407e279f/src//Liquid.Repository.EntityFramework/EntityFrameworkRepository.cs#L28
Custom repositories
Adding custom repositories is difficult due to the way project dependencies are structured. Repository project has a dependency on Domain, hence Domain cannot explicitly depend on Repository.
The only way that worked for me was decoupling Domain Entities from Domain project and creating custom DomainHandlers project.
Suggestion - Modify templates and provide documentation how custom repositories can be added.
Cloud Agnostic Cartridges
While the idea of cloud-agnostic cartridges is appealing, it should support ability to use vendor specific operations. It might not be beneficial for developers to be ignorant of all the features offered by service they depend on. Currently it seems that design principal is either to go full-liquid or full-custom on cartridges, without ability to extend generic functionality
Service Bus Cartridge
For Service Bus in particular, features that are not available:
Due to it's generic nature, a lot of features depend on configuration by convention, without validation or error handling that would make it easier to use #107
For publishing, publisher per entity type is required, making the code more verbose than needed. There's no ability to use underlying service bus client to send JSON/Binary.
When subscribing to a queue, multiple subscribers can be registered, but they are executed by random, there's no orchestration based on type. Hence when 2 subscribers are registered for the same queue, each gets object that was an attempt to deserialize, which causes 1 of the subscribers to always error out.
When processing messages, Liquid doesn't extend the lock on the message in a fashion that service bus processor does (or Azure functions by default in their triggers). Lock timeout is also not a configurable property.
When subscribing to service bus, LiquidWorker didn't work with repositories due to #108
Effort reduction
In general, I didn't notice effort reduction. The liquid version of the API had as much code (commands, handlers) as the generic version. For a simple case where CRUD was accepting filters, custom command, handler, repository and controller had to be created.
Other than CRUD Controller and CRUD Repositories, I'm not sure what other functionality is provided by Core/WebApi/Repo projects, other than swagger and mediatr.
Beta Was this translation helpful? Give feedback.
All reactions