接口提示以下异常:
massage:"Could not found remote action for method:System.Threading.Tasks.Task`1......""
产生此异常的部分原因:
- 本地的代码没有同步到服务器
- K8S-配置中心-配置字典中没有配置RemoteServices
- application services没有创建API Controller
我遇到的是第三种情况,解决方案:
-
在HttpApiHostModule中添加
private void ConfigureConventionalControllers() { Configure<AbpAspNetCoreMvcOptions>(options => { options.ConventionalControllers.Create(typeof(OpeningManagerApplicationModule).Assembly, opts => { opts.RootPath = "xxx";//此为根路径,URL地址中会显示,可根据需要自行配置 }); }); }
-
在ConfigureServices中,调用上述方法
现在即可正常调用远程服务,但此操作会将所有Application层接口批量创建为API Controller存在安全问题
解决方法有两种
- 使用[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]
- 可以使用ApisixRoute,参照自定义的根路径配置正则表达式,使所有application services创建的API Controller均拒绝外部调用。