IAppServices
conventional routing¶
As previously discussed, our Application layer services (henceforth
IAppServices
) can be used as a presentation layer for HTTP based services.
This dynamic Api Controller's presentation layer integrates seamlessly with
ordinary Api Controllers, so developers will always be able to choose the way in
which those services will be exposed and consumed, either by using ordinary
or
dynamic auto-generated Api Controllers
.
The mechanism behind which said IAppServices
are wired as Controllers
is
discussed in following sections.
Discovering IAppService
implementations¶
Types implementing IAppService
will be discovered, registered in DI, and wired
as Api Controllers by the Suite Framework, without any user intervention.
Base route path¶
The Suite Framework will use the same base route path for all IAppService
when
building Mvc Routes
, said base path can be configured through
EndpointsModuleOptions
to suite your needs. By default the value is set to
api
, this means that no matter what your entity name is, it will be routed
from that base root path onwards, thus the route built by the Suite Framework
will look like 'api/{YOUR_ENTITY}/{ENTITY_METHOD}.
Routing convention¶
Given an IAppService
, the Suite Framework will calculate a valid Mvc Route
for every single public method available. Each IAppService
's method will be
given a name, and an http method (verb) constraint, based on its
characteristics. Parameters will also be mapped to QueryString
,
Route template
, Body
or Headers
following conventions explained more in
detail in next sections.
Notice
When more than one method's calculated route collides, the Suite Framework will
create a route only mapped to one of the colliding methods. You must be aware
of this situation and choose suitable method names that the Suite Framework can use
to wire up the IAppService
's methods to.
There is a switch in EndpointsModuleOptions
that you can use to tell the Suite
Framework to stop and fail, in such cases where the conventional routing isn't
able to map the public IAppService
´s methods to valid Mvc routes. By default
the Suite Framework sets the default value to false.
If, for convenience, you want to switch-off the failing behavior, you can
manually set it by injecting EndpointsModuleOptions
, and configuring the
module to suite your purposes.
Taking the following IAppService
as an example:
the convention pipeline will infer the following endpoints:
- GET
rootBasePath/Jobs/AllJobs
mapping toGetAllJobsAsync
. - GET
rootBasePath/Jobs/JobById/{jobId}
mapping toGetJobByIdAsync
. - POST
rootBasePath/Jobs/CreateJob
mapping toCreateJobAsync
. - POST
rootBasePath/Jobs/SearchJobs
mapping toSearchJobsAsync
. - PUT
rootBasePath/Jobs/UpdateJob/{jobId}
mapping toUpdateJobAsync
.
Conventions description¶
The different methods exposed on your IAppServices
will be discovered and
wired according to the following conventions.
EntityName convention¶
The controller is given a name based on the IAppService
's name, removing the
AppService
suffix, if any. The Suite Framework will use this entity name not
only to label the controller but also to conform the base path for that entity
to be accessed throughout Mvc scaffolding. If the type being mapped is an
interface, then the leading "I" letter will also be removed.
Notice
To have a good matching between entity name and 'Api Controller Name' when
using Dynamic Api Controller feature it's recommended that application
services are named with an AppService
suffix.
For example, given the following IAppService
:
C# | |
---|---|
The Suite Framework will do these actions:
- Use
Jobs
as entity name, taking away the leading "I" letter, and trailing "AppService" suffix. - Map entity to an Api Controller named
Jobs
. - Use
Jobs
as the main root path part for the Api Controller routing feature.
HttpMethod convention¶
Notice
This convention should run pretty early in the convention visitors pipeline.
The HTTPMethod
for each member will be assigned mainly based on its name (case
insensitive):
GET
: inferred for methods which name begins with 'Get', 'GetAll' or 'GetList'POST
: inferred for methods which name begins with 'Post', 'Create', 'Insert', 'Add'. Additionally, if the method has a complex parameter which is not anspecial
parameter it will also be assigned anHTTPMethod
of Post.PUT
: inferred for methods which name begins with 'Put' or 'Update'.DELETE
: inferred for methods which name begins with 'Delete', 'DeleteMany', or 'Remove'.PATCH
: inferred for methods which name begins with 'Patch'.
When not matching rule is found, the 'POST' method will be used as default.
Method name¶
Each IAppService
's method name will be extracted, and sanitized as follows, to
conform the Mvc Route
:
- Remove
async
suffix, if any. - Remove
verb prefix
(Get/Post/Delete), if any.
Please note that should the outcome of the convention applied results in an
empty descriptor, the method name without async
prefix will be used as
outcome.
For example, given the following IAppService
:
C# | |
---|---|
Get
prefix will be removed from method name.Async
suffix will be removed from method name.
The Mvc Route
for that entity's method will be:
api/Jobs/AllJobs
, usingGET
http method.
Note that the api
route path part correspond to the base root path outlined
before.
Parameters convention¶
Depending on the type and purpose of the parameter, it can be placed as route template tokens, request body, query strings or http headers.
Let's dive into the details of how the Suite Framework builds up the Mvc Routing
template addressing the burden of wiring up Mvc Routes binding IAppService
's
methods.
'Id' parameters convention¶
If the parameter is named, or ends with "Id", it will be used as part of the template route. For example:
C# | |
---|---|
The method GetJobByIdAsync
will be reached at the following Mvc Route
.
- GET
api/Jobs/JobById/{jobId}
mapping toGetJobByIdAsync
Pay attention to the '{jobId}' token in the route template. This is the way the Suite Framework builds the route mapping when an 'Id' parameter is present.
Primitive parameters convention¶
When a parameter type is primitive, it will be mapped to the QueryString
part
of the Mvc Routing
. The exception of this rule is when the parameter is
considered to be an Id parameter
, in such cases the convention applied will be
the Id parameter
one.
For example, given the following IAppService
:
C# | |
---|---|
The Suite Framework will build up the following Mvc Route
:
api/Jobs/JobById/{jobId}?param1=SomeValue¶m2=true
mapping toGetJobByIdAsync
, withGET
HTTPMethod.
Some things to note here:
jobId
parameter remains a route element, no matter if it is primitive or not, because it's treated as anId parameter
.param1
andparam2
are mapped to theQueryString
routing path part.
Complex parameters convention¶
Note: complex stands for non-primitive types.
When a parameter type is complex, it will be mapped to the Body
part of the
Mvc Routing
and the expected Http method
will be changed to Post, regardless
of what Verb convention
was applied, this condition will overrule any value
defined prior by the convention.
For example, given the following IAppService
:
C# | |
---|---|
The Suite Framework will build up the following Mvc Route
:
api/Jobs/JobBySomeCriteria
mapping toGetJobBySomeCriteriaAsync
, withPOST
http method andjobInfo
as body parameter.
Please note that even though the IAppService
's method could be mapped to GET
http verb, given the GET
prefix in its name, the method will be mapped to
POST
http verb, because of the complex param type of jobInfo
parameter.
Cancellation token convention¶
When a method has a parameter of type CancellationToken
our conventions will
bind and configure MVC routing so that said parameter is router the same way it
would if we were using ordinary Api Controllers.
For example, given the following IAppService
:
C# | |
---|---|
The Suite Framework will build up the following Mvc Route
:
api/Jobs/JobBySomeCriteria
mapping toGetJobBySomeCriteriaAsync
, withPOST
http method andjobInfo
as body parameter. The Cancellation Token parameter will be handled by MVC and it won't be part of the route or parameters in any way whatsoever