
Dynamic Api
Configure Dynamic Api
Configure dynamic Api in the Program.cs file under the MyApp.Host project
cs
new HostApp(new HostAppOptions
{
ConfigureDynamicApi = options =>
{
// API naming in camelCase
options.NamingConvention = NamingConventionEnum.CamelCase;
// Set the global default API prefix
options.DefaultApiPrefix = "api";
/*
* Clear API suffix, without removing the API suffix;
* If not cleared, CreatUserAsync will become CreateUser
*/
options.RemoveActionPostfixes.Clear();
// Custom ActionName handler
options.GetRestFulActionName = (actionName) => actionName;
// Specify assembly to configure all API requests as POST
options.AddAssemblyOptions(GetType().Assembly, httpVerb: "POST");
/*
* Specify assembly to configure URL prefix as api
* E.g.: http://localhost:8010/api/User/CreateUser
*/
options.AddAssemblyOptions(GetType().Assembly, apiPreFix: "api");
/*
* Specify assembly to configure URL prefix as api, and all requests as POST
* E.g.: http://localhost:8010/api/User/CreateUser
*/
options.AddAssemblyOptions(GetType().Assembly, apiPreFix: "api", httpVerb: "POST");
// Generate request methods ["method name prefix"] = "verb"
AppConsts.HttpVerbs = new Dictionary<string, string>()
{
["add"] = "POST",
["create"] = "POST",
["insert"] = "POST",
["submit"] = "POST",
["post"] = "POST",
["get"] = "GET",
["find"] = "GET",
["fetch"] = "GET",
["query"] = "GET",
["update"] = "PUT",
["change"] = "PUT",
["put"] = "PUT",
["batch"] = "PUT",
["delete"] = "DELETE",
["soft"] = "DELETE",
["remove"] = "DELETE",
["clear"] = "DELETE",
};
}
}).Run(args);If no matching request method is found based on the prefix verb,
HttpPostis used
NamingConvention API naming options:
- CamelCase: camelCase naming
- PascalCase: PascalCase naming
- SnakeCase: snake_case naming
- KebabCase: kebab-case naming
- ExtensionCase: extension.case naming
- Custom: Custom API name, set via options.GetRestFulActionName = (actionName) => actionName;
Using Dynamic Api
Add the [DynamicApi(Area = ApiConsts.AreaName)] attribute to the service and inherit the IDynamicApi interface to automatically generate dynamic Api
cs
/// <summary>
/// Module service
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IModuleService, IDynamicApi
{
/// <summary>
/// Get page
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<ModuleListOutput>> GetPageAsync(PageInput<ModuleGetPageDto> input)
{
var key = input.Filter?.Name;
var list = await _moduleRepository.Select
.WhereIf(key.NotNull(), a => a.Name.Contains(key))
.Count(out var total)
.OrderByDescending(true, c => c.Id)
.Page(input.CurrentPage, input.PageSize)
.ToListAsync<ModuleListOutput>();
var data = new PageOutput<ModuleListOutput>()
{
List = list,
Total = total
};
return data;
}
}Note
ApiConsts.AreaName defines app in the path /api/app/module/get
Dynamic Api generates request methods based on prefix verbs. Use the [HttpPost] attribute to change the request method.
New API documentation URL: http://localhost:8010/admin/index.html
Swagger API documentation URL: http://localhost:8010/admin/swagger/index.html
If the service is a dynamic Api, methods with transactions must be defined as virtual for transaction interception to work properly.
Disable Dynamic Api
Add the [NonAction] attribute to the service method to disable dynamic Api generation, making it a public service method
cs
[NonAction]
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}Dynamic Api Rename
Add the following attribute to the service method to rename it
API paths must use absolute paths for renaming to work properly
cs
[HttpPost(template: "/api/[area]/[controller]/[action]")]
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}Dynamic Api Ordering
Add the [Order] attribute to the service for ordering
Smaller values appear first
cs
/// <summary>
/// Module service
/// </summary>
[Order(1010)]
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IModuleService, IDynamicApi
{
}Add the [Order] attribute to the service method for ordering
Larger values appear first
cs
[Order(1010)]
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}Dynamic Api Multiple Groups
Add the [DynamicApi] attribute to the service to specify different groups
cs
/// <summary>
/// Module service
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName, GroupNames = new string[] { AdminConsts.AreaName })]
public class ModuleService : BaseService, IModuleService, IDynamicApi
{
}Add the [ApiGroup] attribute to the service method to specify different groups
API not grouped: [ApiGroup(NonGroup = true)]
cs
[ApiGroup(ApiConsts.AreaName, AdminConsts.AreaName)]
//[ApiGroup(GroupNames = new string[] { ApiConsts.AreaName, AdminConsts.AreaName })]
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}Dynamic Api Return Raw Data
When you don't want to return the unified wrapped data format
json
{
"success": true,
"code": null,
"msg": null,
"data": 1
}Add the [NonFormatResult] attribute to the service method to disable the unified data wrapper and return only the raw data
cs
[NonFormatResult]
public async Task<long> AddAsync(ModuleAddInput input)
{
var entity = input.Adapt<ModuleEntity>();
await _moduleRepository.InsertAsync(entity);
return entity.Id;
}Dynamic Api Authorization 8.3.0
Add the [ApiAccess("permission_code")] attribute to the service method
Note
[ApiAccess("permission_code_1", "permission_code_2", All = true)]
One or more permission codes can be set
All defaults to false - access is granted if any permission code is met. Set to true to require all permission codes.
cs
[ApiAccess("admin:dict:export")]
public async Task<ActionResult> ExportListAsync()
{
...
}Exclude from Swagger Documentation
When you have API endpoints that should not be publicly exposed or displayed in the API documentation, add the [ApiExplorerSettings(IgnoreApi = true)] attribute to the method.
cs
[ApiExplorerSettings(IgnoreApi = true)]
public async Task GetInternalDataForPublicAsync()
{
...
}Disable Operation Logging
When you have API endpoints that should not record operation logs, add [NoOperationLog] to the method.
cs
[NoOperationLog]
public async Task GetDataListAsync()
{
...
}