一、Laobai.Application 业务层的配置

本层中会有一个LaobaiApplicationModule,该类继承自AbpModule,在Laobai.Web.Core中将使用该类作为配置的起点。

本层中放置全部的业务类,默认都继承自AsyncCrudAppServiceAsyncCrudAppService以虚方法默认实现了几个通用的全局方法,如下:

  1. GetAsync
  2. GetAllAsync
  3. CreateAsync
  4. UpdateAsync
  5. DeleteAsync
  6. GetEntityByIdAsync

以上方法会在默认的api中出现,在实现的时候,会将Async从方法名中去掉,最终api的方法类似于GetAll等。

二、全局配置service转为api

官方文档

Laobai.Web.Core项目里的LaobaiWebCoreModule中,有如下配置代码:

1
2
3
4
5
6
7
8
9
10
public override void PreInitialize()
{
...
//配置动态web api
Configuration.Modules.AbpAspNetCore()
.CreateControllersForAppServices(
typeof(LaobaiApplicationModule).GetAssembly(), "laobai"
);
...
}

CreateControllersForAppServices 方法有三个参数:

  1. 第一个参数是要转化为webapi的服务类所在的程序集。

  2. 第二个参数是要生成的webapi中的模块名称。默认使用的是app这个名字。

    猜测:这里可以采用不同的模块名称,将不同的服务放到不同的webapi分类中。不过这样可能需要分程序集了,待验证?

  3. 第三个参数是根据方法名称使用约定的http请求动作,例如GetPostPutDelete等,给的的默认值是true也就是要按照方法名生成不同的请求动作,如果是false,那么所有的动作默认为post请求。具体的实现代码:

    1
    2
    3
    var verb = configuration?.UseConventionalHttpVerbs == true
    ?ProxyScriptingHelper.GetConventionalVerbForMethodName(action.ActionName)
    : ProxyScriptingHelper.DefaultHttpVerb;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public static string GetConventionalVerbForMethodName(string methodName)
    {
    if (methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase))
    {
    return "GET";
    }

    if (methodName.StartsWith("Put", StringComparison.OrdinalIgnoreCase) ||
    methodName.StartsWith("Update", StringComparison.OrdinalIgnoreCase))
    {
    return "PUT";
    }

    if (methodName.StartsWith("Delete", StringComparison.OrdinalIgnoreCase) ||
    methodName.StartsWith("Remove", StringComparison.OrdinalIgnoreCase))
    {
    return "DELETE";
    }

    if (methodName.StartsWith("Patch", StringComparison.OrdinalIgnoreCase))
    {
    return "PATCH";
    }

    if (methodName.StartsWith("Post", StringComparison.OrdinalIgnoreCase) ||
    methodName.StartsWith("Create", StringComparison.OrdinalIgnoreCase) ||
    methodName.StartsWith("Insert", StringComparison.OrdinalIgnoreCase))
    {
    return "POST";
    }

    //Default
    return DefaultHttpVerb;
    }

生成的api默认路径是 /api/services/<第二个参数,默认是app>/<业务类名称>/<方法名称>

三、RemoteServiceAttribute 禁用服务类转成api接口

RemoteServiceAttribute特性的适用范围:类,方法,接口。

需要将该特性类的构造参数设置为false才是禁用,默认是true,也就是不禁用。

  • 指定的方法上打上该标签,那么该方法将被忽略生成api资源。

  • 指定的类上打上该标签,那么类下面的所有方法都不会生成api资源,包括该类的父类AsyncCrudAppService下的几个默认的方法。

  • 注意:指定的接口上打上该标签,不起作用。

四、 使用HttpMethodAttribute设置资源动作

HttpMethodAttribute包括以下几种标签。

  • HttpGet
  • HttpPut
  • HttpDelete
  • HttpHead
  • HttpPost
  • HttpOptions
  • HttpPatch

如果设置了UseConventionalHttpVerbs,那么会根据方法的开头来确定动作的类型, 如果方法的开头不包含默认的几种,则使用Post

1
2
3
4
5
6
[HttpGet]
public async Task<ListResultDto<RoleDto>> LaobaiGetRoles()
{
var roles = await _roleRepository.GetAllListAsync();
return new ListResultDto<RoleDto>(ObjectMapper.Map<List<RoleDto>>(roles));
}

以上示例代码使用HttpGetAttribute,可以指定非特定字符开头的方法为指定的资源动作。有两个事项:

  1. 这个时候,客户端就能以Get方法获取LaobaiGetRoles这个资源了。
  2. HttpGet的构造函数必须使用无参数的那个,否则会根据路由规则生成新的api地址,例如本例中就变成了 /GetRoles,没有与其他api一样的默认的前缀路径,客户端就会找不到资源。