接口提示以下异常:

massage:"Could not found remote action for method:System.Threading.Tasks.Task`1......""

产生此异常的部分原因:

  1. 本地的代码没有同步到服务器
  2. K8S-配置中心-配置字典中没有配置RemoteServices
  3. application services没有创建API Controller

我遇到的是第三种情况,解决方案:

  1. 在HttpApiHostModule中添加

    private void ConfigureConventionalControllers()
    {
        Configure<AbpAspNetCoreMvcOptions>(options =>
        {
            options.ConventionalControllers.Create(typeof(OpeningManagerApplicationModule).Assembly, opts =>
            {
                opts.RootPath = "xxx";//此为根路径,URL地址中会显示,可根据需要自行配置
            });
        });
    }
  2. 在ConfigureServices中,调用上述方法

现在即可正常调用远程服务,但此操作会将所有Application层接口批量创建为API Controller存在安全问题

解决方法有两种

  1. 使用[RemoteService]特性
public void Initialize()
{
    var types = Assembly.GetTypes()
        .Where(IsRemoteService)//过滤非远程服务
        .Where(IsPreferredApplicationServiceType)
        .WhereIf(TypePredicate != null, TypePredicate!);

    foreach (var type in types)
    {
        ControllerTypes.Add(type);
    }
}

private static bool IsRemoteService(Type type)
{
    if (!type.IsPublic || type.IsAbstract || type.IsGenericType)
    {
        return false;
    }

    var remoteServiceAttr = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(type);
    if (remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(type))//依据RemoteServiceAttribute中IsEnabled判断
    {
        return false;
    }

    if (typeof(IRemoteService).IsAssignableFrom(type))
    {
        return true;
    }

    return false;
}

在ConventionalControllerSetting源码中可以看到,在初始化时会自动过滤IsRemoteService方法返回为false的application services。在IsRemoteService方法中,会读取RemoteServiceAttribute,并获取其IsEnabled属性,用以判断返回值。故而只要在无需创建API controller的服务上标注[RemoteService(false)]即可。

我一般的做法为在基础的xxxApplicationService类上标注[RemoteService(false)],需要创建API controller的服务标注[RemoteService]和[Authorize]

  1. 可以使用ApisixRoute,参照自定义的根路径配置正则表达式,使所有application services创建的API Controller均拒绝外部调用。