From ABP Sensei
Guides ABP Framework v10.4 API development: Auto API Controllers, dynamic/static C#/JS client proxies, Swagger, API versioning, and Integration Services.
How this skill is triggered — by the user, by Claude, or both
Slash command
/abp-sensei:abp-apiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Guide to ABP Framework v10.4 API development. Auto API Controllers, Dynamic C# Clients, Static C# Clients, Swagger, API Versioning, Integration Services.
Guide to ABP Framework v10.4 API development. Auto API Controllers, Dynamic C# Clients, Static C# Clients, Swagger, API Versioning, Integration Services.
ABP automatically converts application services into REST API endpoints.
[DependsOn(BookStoreApplicationModule)]
public class BookStoreWebModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly);
});
}
}
| Method Prefix | HTTP Method |
|---|---|
GetList, GetAll, Get | GET |
Put, Update | PUT |
Delete, Remove | DELETE |
Create, Add, Insert, Post | POST |
Patch | PATCH |
| Other | POST (default) |
| Service Method | HTTP Method | Route |
|---|---|---|
GetAsync(Guid id) | GET | /api/app/book/{id} |
GetListAsync() | GET | /api/app/book |
CreateAsync(CreateBookDto input) | POST | /api/app/book |
UpdateAsync(Guid id, UpdateBookDto input) | PUT | /api/app/book/{id} |
DeleteAsync(Guid id) | DELETE | /api/app/book/{id} |
GetEditorsAsync(Guid id) | GET | /api/app/book/{id}/editors |
Route rules:
/api/appBookAppService → book (kebab-case, suffixes removed)id parameter is added to the route: /{id}Async suffix removed)PreConfigure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly, opts =>
{
opts.RootPath = "volosoft/book-store";
});
});
// Route: /api/volosoft/book-store/book/{id}
// Don't expose as an API controller
[RemoteService(IsEnabled = false)]
public class PersonAppService : ApplicationService { }
// Disable only specific methods
[RemoteService(IsEnabled = false)]
public override Task DeleteAsync(Guid id) { }
// Turn non-application-service classes into API controllers
public class MyCustomService : IRemoteService, ITransientDependency
{
public Task<string> GetDataAsync() => Task.FromResult("data");
}
Automatically creates a C# client proxy at runtime.
abp add-package Volo.Abp.Http.Client
[DependsOn(
typeof(AbpHttpClientModule),
typeof(BookStoreApplicationContractsModule)
)]
public class MyClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(
typeof(BookStoreApplicationContractsModule).Assembly
);
}
}
{
"RemoteServices": {
"Default": {
"BaseUrl": "http://localhost:53929/"
}
}
}
public class MyClientService : ITransientDependency
{
private readonly IBookAppService _bookAppService;
public MyClientService(IBookAppService bookAppService) => _bookAppService = bookAppService;
public async Task<List<BookDto>> GetBooksAsync()
{
return await _bookAppService.GetListAsync();
}
}
Handled automatically:
Proxy code is generated at development time (better performance).
abp generate-proxy -t csharp
abp generate-proxy -t csharp --without-contracts # Only the client proxy, without contracts
abp generate-proxy -t csharp --folder MyProxies # Custom folder
// In the HttpApi.Client project
[DependsOn(typeof(AbpHttpClientModule))]
public class MyClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddStaticHttpClientProxies(
typeof(BookStoreApplicationContractsModule).Assembly
);
}
}
| Feature | Dynamic | Static |
|---|---|---|
| Performance | Runtime generation | Compile-time |
| Development | Easy, automatic | Re-generation required |
| API change | Detected automatically | Manual re-generation |
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class MyHttpApiModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My API",
Version = "v1",
Description = "My API Description"
});
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1");
});
}
}
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
// Versioned application service
[RemoteService]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class BookAppService : ApplicationService, IBookAppService
{
[Obsolete("Use the new version instead")]
public virtual Task<BookDto> GetAsync(Guid id) { }
}
// Versioned controller
[Area("app")]
[Route("api/v{version:apiVersion}/app/book")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class BookController : AbpController { }
context.Services.AddAbpSwaggerGenWithVersioning(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
options.SwaggerDoc("v2", new OpenApiInfo { Title = "My API", Version = "v2" });
});
Integration services are used for direct communication between modules (instead of HTTP).
// Integration service interface (in Application.Contracts)
public interface IProductIntegrationService : IIntegrationService
{
Task<ProductDto> GetProductAsync(Guid id);
Task CreateProductAsync(CreateProductDto input);
}
// Implementation (in Application)
[ExposeServices(typeof(IProductIntegrationService))]
public class ProductIntegrationService : ApplicationService, IProductIntegrationService
{
private readonly IRepository<Product, Guid> _productRepository;
public ProductIntegrationService(IRepository<Product, Guid> productRepository) =>
_productRepository = productRepository;
public async Task<ProductDto> GetProductAsync(Guid id)
{
var product = await _productRepository.GetAsync(id);
return ObjectMapper.Map<Product, ProductDto>(product);
}
public async Task CreateProductAsync(CreateProductDto input)
{
var product = ObjectMapper.Map<CreateProductDto, Product>(input);
await _productRepository.InsertAsync(product);
}
}
With the IIntegrationService marker interface, ABP automatically calls these services:
HttpClient manually[Obsolete]/api/my-module instead of /api/appnpx claudepluginhub burakdmir/abp-skills --plugin abp-senseiProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.