Search code examples
c#asp.netabp-framework

How do you customize the Route on abp CrudAppService / AsyncCrudAppService


I am experimenting with the abp CrudAppService (https://docs.abp.io/en/abp/latest/Application-Services#crud-application-services), which allows me to set up CRUD endpoints with minimal code.

As an example, I can create the following base class:

public class BaseAsyncCrudAppService<TEntity, TDto> : AsyncCrudAppService<TEntity, TDto, Guid, PagedAndSortedResultRequestDto,
    TDto, TDto> where TEntity : class, IEntity<Guid> where TDto : IEntityDto<Guid>
{
    public BaseAsyncCrudAppService(IRepository<TEntity, Guid> repository)
        : base(repository)
    {

    }
}

And then create enpoint sets like these:

public class MyFooAppService : BaseAsyncCrudAppService<MyFooEntity, MyFooDto>,
    IMyFooAppService
{
    
    public MyFooAppService(IRepository<MyFooEntity, Guid> repository) : base(repository)
    {
    }
}

And

public class MyBarAppService : BaseAsyncCrudAppService<MyBarEntity, MyBarDto>,
    IMyBarAppService
{
    
    public MyBarAppService(IRepository<MyBarEntity, Guid> repository) : base(repository)
    {
    }
}

This will produce the following endpoints:

GET /api/services/app/MyFoo/Get
GET /api/services/app/MyFoo/GetAll
POST /api/services/app/MyFoo/Create
PUT /api/services/app/MyFoo/Update
DELETE /api/services/app/MyFoo/Delete


GET /api/services/app/MyBar/Get
GET /api/services/app/MyBar/GetAll
POST /api/services/app/MyBar/Create
PUT /api/services/app/MyBar/Update
DELETE /api/services/app/MyBar/Delete

What I would like to know is how I could alter the path where these endpoints get served. I don't need to do it individually for each method, but I would like to set it for example

GET /api/services/app/baz/MyFoo/Get
GET /api/services/app/baz/MyFoo/GetAll
POST /api/services/app/baz/MyFoo/Create
PUT /api/services/app/baz/MyFoo/Update
DELETE /api/services/baz/app/MyFoo/Delete

If were to code the endpoints manually, I would do it like this:

[Route("api/services/app/baz/[controller]/Get")]
public async Task GetMyFoo(Guid id)
{
    ...
}

Is there a way to do this on class level on the MyFooAppService class?


Solution

  • Decorate the base class with Microsoft.AspNetCore.Mvc.Route attribute, e.g. [Route("/api/services/app/baz/[controller]")].

    [Route("/api/services/app/baz/[controller]")]
    public class BaseAsyncCrudAppService<TEntity, TDto> : AsyncCrudAppService<TEntity, TDto, Guid, PagedAndSortedResultRequestDto,
        TDto, TDto> where TEntity : class, IEntity<Guid> where TDto : IEntityDto<Guid>
    {
        public BaseAsyncCrudAppService(IRepository<TEntity, Guid> repository)
            : base(repository)
        {
    
        }
    }
    

    To customize the routes of the individual endpoints, you can override the methods and decorate them with HTTP verb attributes,

    For example, [HttpGet("/new/root/here")]

    [HttpGet("/new/root/here")]
    public override Task<TDto> GetAsync(EntityDto<Guid> id)
    {
       return base.GetAsync(id);
    }
    

    would produce endpoint

    GET  /new/root/here/
    

    To extend the route specified on class level, omit the leading '/'.

    For example [HttpGet("sub/root/here/")] would make the endpoint available at

    GET  /api/services/app/baz/[controller]/sub/root/here/