GraphQL Generic UIs¶
The Angular frontend includes features to generate UI based off GQL Queries and Mutations. These are the steps required on the backend to expose them.
From GQL to Generic UIs¶
These are the high level steps required to a GQL Query or Mutation and be able to generate a generic UI off it and display it in an App, in this case AdminCenter.
Declare DTOs¶
DTOs for GraphQL are declared in the .Application.Contracts
layer of Backend
Services, in the namespace .Application.GraphQL
.
It is recommended to create this type of objects as record
, if possible. Also,
make sure to follow the conventions defined
here for the
naming of the DTOs.
DTOs for Mutations can use nullability to validate that an argument is or not required. i.e if a non nullable property is not provided when executing the Mutation, it won't be executed.
DTOs for Queries must have all fields nullable, since GQL queries don't query all fields of an entity at once.
Important
The DTOs must have their Id field called CorrelationId
and if
they have a Name
field, it should be mapped to DisplayName
Example:
Expose Queries¶
Backend services should expose queries for their entities.
When we depend on the GraphQL Module, we can use ExposeInPublicApi
to expose
queries of an Entity projected to a DTO, under the specified name.
C# | |
---|---|
Then, we can run our service and access http://localhost:5001/graphql to see the GraphQL Playground, where we can test a simple query to see everything works ok. For example, a simple query would be:
Expose Hierarchical Queries¶
Backend services should expose hierarchical queries for their entities, if they have a parent-child self dependency.
This type of query is a must do for Tree List Pages. To expose an hierarchical query, there are 4 points to take into account:
- GraphQL module is imported.
- The entity has an specification for child elements. Example:
C# | |
---|---|
- The
ExposeHierarchicalQuery
is added to the GraphQL module using the specification from the previous step. - An expression to select the entity's
CorrelationId
must be provided.
Example:
C# | |
---|---|
This method will add a query with the name provided and Children
appended at
the end. From the previous example, if we specified positions
, the module will
expose a query called positionsChildren
. At the GraphQL playground we could
perform the following tests:
- Example 1: This will return all root positions.
- Example 2: This will return the children from the position provided.
GraphQL | |
---|---|
Please note that a childCount
attribute is automatically added to the
projected DTO by the Suite Framework, this is specially useful to know
beforehand wether each node has / hasn't children, and helps the UI to render
the UI components correctly.
Expose Mutations¶
Application services should expose mutations for executing the use cases the UI requires.
Similar to queries, when depending on the GraphQL Module we can quickly expose the Publishing of an MT Message as a GQL Mutation.
We still are required to provide a DTO tho, this is so we don't leak the internal messaging API with the frontend.
By providing a DTO, we can guarantee that the public API is not broken, since we can then change the message we publish, or do some other logic when the mutation is executed.
We are also required to provide an expression which returns a field of the MT Message where we want a NewId generated.
Publishing a Message¶
We can use ExposeMessageAsMutation
to generate a mutation that will publish a
Message. This mutation will immediately return the generated CorrelationId.
C# | |
---|---|
If the message being exposed requires the ID of the logged in user, we need to provide an expression which returns the field where we want the ID of the user to be automatically set.
C# | |
---|---|
We are using the version of the ExposeMessageAsMutation
method that takes a
builder that allows us to configure the behavior. The UseIdField
indicates
where we want the new ID for the message to be stored, usually CorrelationId
and the UseCurrentUserIdField
indicates where we want the current user ID to
be set.
Important
If the exposed message requires a logged in user and none is present, the mutation will return an Authentication error.
Request/Response Message¶
We can pass a third generic parameter to ExposeMessageAsMutation
to set the
response message type. This will cause the message to be sent using the
Request/Response pattern, the GraphQL call will wait for the response message to
arrive before returning.
C# | |
---|---|
We can also pass a forth generic parameter to ExposeMessageAsMutation
to set
the type of the DTO to be returned. The mutation will automatically mapped the
response message into the return DTO using Automapper.
C# | |
---|---|
Important
Make sure to modify your Saga or Consumer to Respond to that Request.
Add RemoteSchema to BFF¶
The final steps for us to see the Queries and Mutations in the UI is to add the backend service as a Remote Schema in the Backend for Frontend.
The BFF combines the queries/mutations of all Remote Schemas into a single schema, which is what the front end uses. This is achieved through a feature called Schema Federation.
Generic UIs¶
The Suite Framework for Angular has modules for generating user interfaces based off Queries and Mutations.