项目

自动 API 控制器

一旦您创建了一个 应用服务 ,通常您会希望创建一个 API 控制器,将此服务作为 HTTP (REST) API 端点公开。典型的 API 控制器除了将方法调用重定向到应用服务并使用诸如 [HttpGet]、[HttpPost]、[Route] 等属性配置 REST API 之外,几乎不执行其他操作。

ABP 可以自动地按照约定将您的应用服务配置为 API 控制器。大多数情况下,您不需要关心其详细配置,但完全可以对其进行完全自定义。

配置

基本配置很简单。只需配置 AbpAspNetCoreMvcOptions 并使用 ConventionalControllers.Create 方法,如下所示:

[DependsOn(BookStoreApplicationModule)]
public class BookStoreWebModule : AbpModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        PreConfigure<AbpAspNetCoreMvcOptions>(options =>
        {
            options
                .ConventionalControllers
                .Create(typeof(BookStoreApplicationModule).Assembly);
        });
    }
}

此示例代码配置了包含 BookStoreApplicationModule 类的程序集中的所有应用服务。下图显示了在 Swagger UI 上生成的 API。

bookstore-apis

示例

一些示例方法名称以及按约定计算出的相应路由:

服务方法名称 HTTP 方法 路由
GetAsync(Guid id) GET /api/app/book/
GetListAsync() GET /api/app/book
CreateAsync(CreateBookDto input) POST /api/app/book
UpdateAsync(Guid id, UpdateBookDto input) PUT /api/app/book/
DeleteAsync(Guid id) DELETE /api/app/book/
GetEditorsAsync(Guid id) GET /api/app/book//editors
CreateEditorAsync(Guid id, BookEditorCreateDto input) POST /api/app/book//editor

HTTP 方法

ABP 在确定服务方法(操作)的 HTTP 方法时使用命名约定:

  • Get: 如果方法名称以 'GetList'、'GetAll' 或 'Get' 开头,则使用。
  • Put: 如果方法名称以 'Put' 或 'Update' 开头,则使用。
  • Delete: 如果方法名称以 'Delete' 或 'Remove' 开头,则使用。
  • Post: 如果方法名称以 'Create'、'Add'、'Insert' 或 'Post' 开头,则使用。
  • Patch: 如果方法名称以 'Patch' 开头,则使用。
  • 否则,默认使用 Post

如果您需要为特定方法自定义 HTTP 方法,则可以使用标准的 ASP.NET Core 属性之一([HttpPost]、[HttpGet]、[HttpPut]... 等)。这需要将 Microsoft.AspNetCore.Mvc.Core nuget 包添加到包含该服务的项目中。

路由

路由基于一些约定计算得出:

  • 它总是以 '/api' 开头。
  • 然后是路由路径。默认值为 '/app',可以像下面这样配置:
Configure<AbpAspNetCoreMvcOptions>(options =>
{
    options.ConventionalControllers
        .Create(typeof(BookStoreApplicationModule).Assembly, opts =>
            {
                opts.RootPath = "volosoft/book-store";
            });
});

那么获取书籍的路由将是 '/api/volosoft/book-store/book/'。此示例使用了两个层级的根路径,但您通常使用单层深度。

  • 然后是规范化的控制器/服务名称。规范化会移除 'AppService'、'ApplicationService' 和 'Service' 后缀,并将其转换为短横线命名法 (kebab-case)。如果您的应用服务类名是 'ReadingBookAppService',那么它将变为 '/reading-book'。
    • 如果您想自定义命名,请设置 UrlControllerNameNormalizer 选项。它是一个 func 委托,允许您为每个控制器/服务确定名称。
  • 如果方法有一个 'id' 参数,则将 '/' 添加到路由中。
  • 然后,如果需要,它会添加操作名称。操作名称从服务上的方法名获取,并通过以下方式规范化:
    • 移除 'Async' 后缀。如果方法名是 'GetPhonesAsync',则变为 'GetPhones'。
    • 移除 HTTP 方法前缀。根据选定的 HTTP 方法,移除 'GetList'、'GetAll'、'Get'、'Put'、'Update'、'Delete'、'Remove'、'Create'、'Add'、'Insert'、'Post' 和 'Patch' 前缀。因此,'GetPhones' 对于 GET 请求来说,'Get' 前缀是重复的,所以变为 'Phones'。
    • 将结果转换为短横线命名法 (kebab-case)
    • 如果生成的操作名称为空,则不添加到路由中。如果不为空,则添加到路由中(如 '/phones')。对于 'GetAllAsync' 方法名,它将为空;对于 'GetPhonesAsync' 方法名,它将为 'phones'。
    • 可以通过设置 UrlActionNameNormalizer 选项来自定义规范化。它是一个为每个方法调用的操作委托。
  • 如果存在另一个带有 'Id' 后缀的参数,则它也会作为最终路由段添加到路由中(如 '/phoneId')。

自定义路由计算

IConventionalRouteBuilder 用于构建路由。默认由 ConventionalRouteBuilder 实现,并按上述方式工作。您可以替换/覆盖此服务以自定义路由计算策略。

版本 3.x 风格的路由计算

在版本 4.0 之前,路由计算是不同的。它使用的是驼峰命名法约定,而 ABP 版本 4.0+ 使用短横线命名法。如果您使用旧的路由计算策略,请遵循以下方法之一:

  • options.ConventionalControllers.Create(...) 方法的选项中,将 UseV3UrlStyle 设置为 true。示例:
options.ConventionalControllers
    .Create(typeof(BookStoreApplicationModule).Assembly, opts =>
        {
            opts.UseV3UrlStyle = true;
        });

此方法仅影响 BookStoreApplicationModule 的控制器。

  • AbpConventionalControllerOptionsUseV3UrlStyle 设置为 true,以全局设置它。示例:
Configure<AbpConventionalControllerOptions>(options =>
{
    options.UseV3UrlStyle = true;
});

全局设置会影响模块化应用程序中的所有模块。

服务选择

创建约定式 HTTP API 控制器实际上并非应用服务独有的功能。

IRemoteService 接口

如果一个类实现了 IRemoteService 接口,那么它会被自动选为约定式 API 控制器。由于应用服务本质上实现了该接口,因此它们被视为天然的 API 控制器。

RemoteService 属性

RemoteService 属性可用于将类标记为远程服务,或者为固有实现了 IRemoteService 接口的特定类禁用远程服务。示例:

[RemoteService(IsEnabled = false)] //或直接写 [RemoteService(false)]
public class PersonAppService : ApplicationService
{

}

TypePredicate 选项

您可以通过提供 TypePredicate 选项进一步筛选要成为 API 控制器的类:

services.Configure<AbpAspNetCoreMvcOptions>(options =>
{
    options.ConventionalControllers
        .Create(typeof(BookStoreApplicationModule).Assembly, opts =>
            {
                opts.TypePredicate = type => { return true; };
            });
});

您不必为每个类型都返回 true,可以检查它,如果不想将此类型公开为 API 控制器,则返回 false

API 探测

API 探测是一项服务,使客户端能够探查 API 结构。Swagger 使用它来创建端点的文档和测试 UI。

默认情况下,约定式 HTTP API 控制器会自动启用 API 探测。使用 RemoteService 属性在类或方法级别控制它。示例:

[RemoteService(IsMetadataEnabled = false)]
public class PersonAppService : ApplicationService
{

}

禁用了 IsMetadataEnabled,这将从 API 探测中隐藏此服务,使其不可被发现。但是,了解确切 API 路径/路由的客户端仍然可以使用它。

替换或移除控制器

除了 覆盖控制器 外,您还可以使用一个完全独立的控制器来替换框架或模块中的控制器。

它们具有相同的 路由 ,但可以具有不同的输入和输出参数。

替换内置的 AbpApplicationConfigurationController

ReplaceControllersAttribute 指示要替换的控制器类型。

[ReplaceControllers(typeof(AbpApplicationConfigurationController))]
[Area("abp")]
[RemoteService(Name = "abp")]
public class ReplaceBuiltInController : AbpController
{
    [HttpGet("api/abp/application-configuration")]
    public virtual Task<MyApplicationConfigurationDto> GetAsync(MyApplicationConfigurationRequestOptions options)
    {
        return Task.FromResult(new MyApplicationConfigurationDto());
    }
}

public class MyApplicationConfigurationRequestOptions : ApplicationConfigurationRequestOptions
{

}

public class MyApplicationConfigurationDto : ApplicationConfigurationDto
{

}

移除控制器

配置 AbpAspNetCoreMvcOptionsControllersToRemove 以移除控制器。

services.Configure<AbpAspNetCoreMvcOptions>(options =>
{
    options.ControllersToRemove.Add(typeof(AbpLanguagesController));
});

另请参阅

在本文档中