Skip to content

How to add a new WebApiEndpoint

This involves two parts:

  1. Create WebApiEndpoint
  2. Specify ApiEndpointDefinition

Create WebApiEndpoint

WebApiEndpoint separates out queries and commands.

Query maps to returning data without side-effects i.e. a HttpMethod.GET

Command maps to things that have side-effects i.e. a HttpMethod.Post | HttpMethod.Put | HttpMethod.Patch | HttpMethod.Delete

When you know which one you are creating, then you use the fluent API to allow you to specify and create a WebApiEndpoint.

Depending on the type of WebApiEndpoint you are creating, you may also have to create a mapper, the fluent API will show you what you need to create.

Query

Inherits from 'QueryWebApiEndpoint'. This a fluent API, that allows you to specify the request and response types.

Options available:

Note what 'ApiEndpoint' is inheriting.

Query No Request

QueryWebApiEndpoint.NoRequest

Query Request<TDomain>

QueryWebApiEndpoint.Request<Query>

Query Request<TDto, TDomain>

QueryWebApiEndpoint.Request<QueryDto, Query>

Command

Inherits from 'CommandWebApiEndpoint'. This a fluent API, that allows you to specify the request and response types.

Options available:

Note what 'ApiEndpoint' is inheriting.

Command RequestPlainText<TApiEndpoint>

CommandWebApiEndpoint.RequestPlainText<ApiEndpoint>

Command Request<TDomain>

CommandWebApiEndpoint.Request<Query>

Command Request<TDto, TDomain>

CommandWebApiEndpoint.Request<QueryDto, Query>

Mapper

If required you will need to specify the mapper type as well. See mappers for more information.

Mapper types are specified using the following:

.Mapper

CommandWebApiEndpoint.Request<CommandDto, Command>.Response<BlogDto, Blog>.Mapper<Mapper, BlogMapper>

Specify ApiEndpointDefinition

ApiEndpointDefinition's allow you to specify the WebApi (REST) route(s) that are connected to your WebApiEndpoint.

In order to connect it to WebApiEndpoints, you need to specify it like this:

definitionBuilder.Web()

This will then provide a fluent interface to set the WebApiEndpoint route configurations.

The next thing to do is to specify either 'Query' or 'Command'.

ApiEndpointDefinition - Query

The first thing to do it to specify the type of the WebApiEndpoint.

.Query<BlogGet.ApiEndpoint>(builder => 

This give you access to the query specific route builder.

Now you can specify the route:

builder.Route("blog")
or route with parameters
builder.Route("blog/{Id}", ("Id", typeof(long)))

ApiVersion

You can optionally specify a ApiVersion, if you don't choose one the default ApiVersion from configuration will be used:

.Version(WebApiEndpointVersions.V1_0)

Security

You can optionally secure the route.

.RequireAuthorization()

Permission

.RequirePermissionAuthorization(Authorization.Permission.Admin)

Claim

.RequireClaimAuthorization(Authorization.ClaimType.Admin, Authorization.Claim.Admin)
Specify your own handler
var claimsRequired = new List<ClaimRecord>{new ClaimRecord(Authorization.ClaimType.Admin, Authorization.Claim.Admin)};

.RequireClaimAuthorization(authorizationHandlerContext => !claimsRequired.Except(authorizationHandlerContext.User.Claims.Select(x => new ClaimRecord(x.Type, x.Value))).Any());

Role

.RequireRoleAuthorization(Authorization.Role.Admin)

OpenApi

You can optionally specify OpenApi summary and description:

.Summary("Get Blogs").Description("Get Blogs")

ApiEndpointDefinition - Command

The first thing to do it to specify the type of the WebApiEndpoint.

.Command<BlogCreate.ApiEndpoint>(builder => 

This give you access to the command specific route builder.

Now you can specify the route, but in order to do that you have to pick the HttpMethod (Post | Put | Patch | Delete) you want to use:

Post

builder.Post("blog")
or with parameters
builder.Post("blog/{Id}", ("Id", typeof(long)))

Put

builder.Put("blog")
or with parameters
builder.Put("blog/{Id}", ("Id", typeof(long)))

Patch

builder.Patch("blog")
or with parameters
builder.Patch("blog/{Id}", ("Id", typeof(long)))

Delete

builder.Delete("blog")
or with parameters
builder.Delete("blog/{Id}", ("Id", typeof(long)))

ApiVersion

You can optionally specify a ApiVersion, if you don't choose one the default ApiVersion from configuration will be used:

.Version(WebApiEndpointVersions.V1_0)

Security

You can optionally secure the route.

.RequireAuthorization()

Permission

.RequirePermissionAuthorization(Authorization.Permission.Admin)

Claim

.RequireClaimAuthorization(Authorization.ClaimType.Admin, Authorization.Claim.Admin)
Specify your own handler
var claimsRequired = new List<ClaimRecord>{new ClaimRecord(Authorization.ClaimType.Admin, Authorization.Claim.Admin)};

.RequireClaimAuthorization(authorizationHandlerContext => !claimsRequired.Except(authorizationHandlerContext.User.Claims.Select(x => new ClaimRecord(x.Type, x.Value))).Any());

Role

.RequireRoleAuthorization(Authorization.Role.Admin)

OpenApi

You can optionally specify OpenApi summary and description:

.Summary("Create Blog").Description("Create Blog")

Complete example

public class ApiEndpointDefinition : IApiEndpointDefinition
{
    public void Configure(ApiEndpointDefinitionBuilder definitionBuilder)
    {
        definitionBuilder.Web()
                         .Command<BlogCreate.ApiEndpoint>(builder => builder.Post("blog")
                                                                            .RequireAuthorization()
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Create Blog").Description("Create Blog"))
                         .Command<BlogDelete.ApiEndpoint>(builder => builder.Delete("blog/{Id}", ("Id", typeof(long)))
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Delete Blog").Description("Delete Blog"))
                         .Query<BlogGet.ApiEndpoint>(builder => builder.Route("blog")
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Get Blogs").Description("Get Blogs"))
                         .Query<BlogGetById.ApiEndpoint>(builder => builder.Route("blog/{Id}", ("Id", typeof(long)))
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Get Blogs By Id").Description("Get Blogs By Id"))
                         .Command<BlogUpdate.ApiEndpoint>(builder => builder.Put("blog")
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Update Blog").Description("Update Blog"))
                         .Query<BlogGetAsyncEnumerable.ApiEndpoint>(builder => builder.Route("blog-async")
                                                                            .Version(WebApiEndpointVersions.V1_0).Summary("Get Blogs").Description("Get Blogs"));
    }
}