I have a module named BaseComponent with following AppService:
public interface IStaticDataTypeAppService : IApplicationService
{
Task<LoadResult> GetListAsync(DataSourceLoadOptionsCustomized options);
Task<BaseComponentResponseDto> BatchUpdateAsync(List<DXBatchUpdate> changes);
Task<StaticDataTypeViewDto?> GetNameByCodeAsync(string code);
}
public class StaticDataTypeAppService : BaseComponentAppService, IStaticDataTypeAppService
{
private readonly IStaticDataTypeRepository _staticDataTypeRepository;
private readonly IStaticDataStructureRepository _staticDataStructureRepository;
private readonly IEmployeeRepository _employeeRepository;
private readonly IStringLocalizer<BaseComponentResource> _baseLocalizer;
public StaticDataTypeAppService(
IStaticDataTypeRepository staticDataTypeRepository,
IStaticDataStructureRepository staticDataStructureRepository,
IEmployeeRepository employeeRepository,
IStringLocalizer<BaseComponentResource> baselocalizer
)
{
_staticDataTypeRepository = staticDataTypeRepository;
_staticDataStructureRepository = staticDataStructureRepository;
_employeeRepository = employeeRepository;
_baseLocalizer = baselocalizer;
}
...
}
I use this module in AMLReportService as following:
public interface ICustomStaticDataTypeAppService : IStaticDataTypeAppService
{
}
public class CustomStaticDataTypeAppService : StaticDataTypeAppService, ICustomStaticDataTypeAppService
{
public CustomStaticDataTypeAppService(IStaticDataTypeRepository staticDataTypeRepository, IStaticDataStructureRepository staticDataStructureRepository, IEmployeeRepository employeeRepository, IStringLocalizer<BaseComponentResource> baselocalizer) : base(staticDataTypeRepository, staticDataStructureRepository, employeeRepository, baselocalizer)
{
}
}
The purpose that I have to create Custom AppService for IStaticDataTypeAppService is: this module will be used in multiple services, so all of its APIs need to be renamed.
In AMLReportService swagger, I can see custom APs and work fine:

Static C# proxy is also generated normally as following:
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ICustomStaticDataTypeAppService), typeof(CustomStaticDataTypeClientProxy))]
public partial class CustomStaticDataTypeClientProxy : ClientProxyBase<ICustomStaticDataTypeAppService>, ICustomStaticDataTypeAppService
{
public virtual async Task<LoadResult> GetListAsync(DataSourceLoadOptionsCustomized options)
{
return await RequestAsync<LoadResult>(nameof(GetListAsync), new ClientProxyRequestTypeValue
{
{ typeof(DataSourceLoadOptionsCustomized), options }
});
}
public virtual async Task<BaseComponentResponseDto> BatchUpdateAsync(List<DXBatchUpdate> changes)
{
return await RequestAsync<BaseComponentResponseDto>(nameof(BatchUpdateAsync), new ClientProxyRequestTypeValue
{
{ typeof(List<DXBatchUpdate>), changes }
});
}
public virtual async Task<StaticDataTypeViewDto> GetNameByCodeAsync(string code)
{
return await RequestAsync<StaticDataTypeViewDto>(nameof(GetNameByCodeAsync), new ClientProxyRequestTypeValue
{
{ typeof(string), code }
});
}
}
But in client side, in ServiceProxyScript, I can't find those APIs, I don't know why it's not generated (Only APIs in BaseComponent module are not generated, other APIs in AMLReportService are generated normally). Please help.
9 Answer(s)
-
0
- Solution In MVC UI, the dynamic JavaScript proxies (/Abp/ServiceProxyScript) only include application services that are exposed by conventional HTTP API controllers in the current host and not excluded by [RemoteService]. Since your Swagger shows the custom endpoints correctly and the static C# client proxy is generated, the missing entries in ServiceProxyScript typically come from one of the following:
- The custom app service type is not picked up by the Auto API Controller convention in the AMLReportService HttpApi layer.
- The service is exposed under a different remote service name or API group and the JS proxy endpoint you load does not include that module/service.
- The service or its methods are excluded via [RemoteService(false)] on the class or methods.
- You are loading the ServiceProxyScript from a different host (tiered) that doesn’t expose those controllers.
Fix/checklist:
- Ensure conventional HTTP API controllers are created for the AMLReportService application assembly. In your AMLReportService HttpApi project/module (typically Xxx.HttpApi), configure Auto API controllers for the assembly that contains CustomStaticDataTypeAppService:
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; [DependsOn( typeof(AbpAspNetCoreMvcModule), typeof(AmlReportServiceApplicationModule) // your app module )] public class AmlReportServiceHttpApiModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure<AbpAspNetCoreMvcOptions>(options => { options.ConventionalControllers.Create(typeof(AmlReportServiceApplicationModule).Assembly); }); } }If CustomStaticDataTypeAppService resides in a different assembly, pass that assembly instead.
- Do not exclude the service with [RemoteService(false)]. If you have base classes or interfaces with that attribute, override it on the derived service:
[RemoteService(true)] public class CustomStaticDataTypeAppService : StaticDataTypeAppService, ICustomStaticDataTypeAppService { // ... }Verify the remote service name/group for your controller so the JS proxy endpoint includes it. If you changed the controller name with [RemoteService(Name = "AmlReportService")] or ApiExplorerGroupName, ensure you request the correct group from the ServiceProxyScript if you are filtering by module. For example:
- Default full script: /Abp/ServiceProxyScript
- Filtered: /Abp/ServiceProxyScript?module=AmlReportService (only if you configured modules and consume a subset)
If you are in a tiered setup, ensure the MVC/UI application points to and loads the ServiceProxyScript from the AMLReportService HttpApi host that actually exposes the controllers. Load and inspect:
- https://your-amlreportservice-host/Abp/ServiceProxyScript Search for “customStaticDataType” or your service/method names there. If it appears on the AMLReportService host but not on your MVC host, then your MVC app is including the script from its own host rather than from AMLReportService. Include the script tag from the correct remote host or configure the UI to fetch remote proxies.
Use only async methods in app services. JS proxies are generated for the HTTP endpoints created from async methods (Task/Task<T>) on IApplicationService. Your signatures already look async; keep that.
Clear caches/restart and re-check: since ServiceProxyScript is generated on request, restart the HttpApi host after code changes and hard-refresh the browser to avoid caching.
Quick verification flow:
- Browse the exact host that exposes the APIs: {AmlReportServiceHost}/Abp/ServiceProxyScript and search for “customStaticDataType”.
- If missing there, your conventional controller mapping isn’t including the assembly. Add options.ConventionalControllers.Create(...) as shown.
- If present there but missing on the MVC app, make the MVC app include that same script from the AMLReportService host.
- Sources
- Dynamic JavaScript Proxies: ServiceProxyScript endpoint (validated)
- https://abp.io/docs/latest/framework/ui/mvc-razor-pages/dynamic-javascript-proxies
- ABP GitHub (framework reference)
- https://github.com/abpframework/abp
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
I already configured conventional controller like this but it didn't help:
Configure<AbpAspNetCoreMvcOptions>(options => { options.ConventionalControllers .Create(typeof(AMLReportServiceApplicationModule).Assembly, opts => { opts.RootPath = AMLReportServiceRemoteServiceConsts.ModuleName; opts.RemoteServiceName = AMLReportServiceRemoteServiceConsts.RemoteServiceName; }); }); -
0
hi
Has your
AMLmodule added theHttpApimodule/layer?HttpApiwill contain the controllers that implement the app services.And your Web should add
AML.HttpApi.Thanks,.
-
0
Hi,
In
HttpApiI don't have any controller that implement the app service mannualy. The controllers are generated automatically by conventional controllers configured as my previous comment. Do I need to addHttpApi?For your better suggestion. If I change my code like this:
public class CustomStaticDataTypeAppService : StaticDataTypeAppService, IStaticDataTypeAppService { public CustomStaticDataTypeAppService(IStaticDataTypeRepository staticDataTypeRepository, IStaticDataStructureRepository staticDataStructureRepository, IEmployeeRepository employeeRepository, IStringLocalizer<BaseComponentResource> baselocalizer) : base(staticDataTypeRepository, staticDataStructureRepository, employeeRepository, baselocalizer) { } }It means, if I don't use
ICustomStaticDataTypeAppService, useIStaticDataTypeAppServicedirectly, javascript proxy is generate normally. But the problem is APIs will be the same name because it use the same interface, so other services will call wrong APIs of a certain service. -
0
hi
For reusable modules, you should add controllers to HttpApi, just like all ABP modules.
https://github.com/abpframework/abp/tree/dev/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity
Thanks.
-
0
OK, let's use Identity module as an example. Now I want to use this module in 2 services concurently. As my understanding, all tables of Identity module will be created in database of each service. Right?
But the code to manage all those tables is located in Identity module. So how to reuse UI in Indentity module and get correct data of Identity module for each service? It means each service will have the same UI, just different data.
That is the problem I'm facing. Please show me your solution to reuse Identity module.
-
0
hi
Now I want to use this module in 2 services concurently. As my understanding, all tables of Identity module will be created in database of each service. Right
If your two services use independent database, Yes .
But the code to manage all those tables is located in Identity module. So how to reuse UI in Indentity module and get correct data of Identity module for each service? It means each service will have the same UI, just different data.
The
Identity.Webis a UI layer, it will use app service interfaces to manage the data.In a single-layer app. It directly depends on application services. In a tiered app. It will use a C# proxy to send HTTP requests to your api website.
https://abp.io/docs/latest/framework/api-development/dynamic-csharp-clients https://abp.io/docs/latest/framework/api-development/static-csharp-clients
-
0
But I still don't understand how each service can call right API to get data. Now I have the menu like this: Service A User Service B User
Please pay attention that all UI are hosted in Web project. When user click in User menu in each service, but it's the same URL, how ABP understand to navigate to different APIs of each service?
-
0
hi
Different pages will use different
AppService, and abp will know which AppService's URL to use.{ "RemoteServices": { "Default": { "BaseUrl": "http://localhost:53929/" }, "ServiceA": { "BaseUrl": "http://localhost:48393/" }, "ServiceB": { "BaseUrl": "http://localhost:48394/" } } }https://abp.io/docs/latest/framework/api-development/dynamic-csharp-clients#multiple-remote-service-endpoints
Thanks.