Open Closed

Dynamic HTTP Proxy throws “Could not find remote action” although API endpoint exists and is reachable #10308


User avatar
0
devchase321 created

Problem Description

I am facing an issue with ABP’s Dynamic HTTP Client Proxy. in WebPublic Project

I have an Application Service method:

Task<List<TeamMemberDto>> GetAllAsync();

And a working HttpApi controller endpoint:

GET /api/app/user-detail-info/all

✔ Direct call works

Calling the endpoint directly in the browser or via Postman works correctly:

https://localhost:44364/api/app/user-detail-info/all

❌ Proxy call fails

When the method is invoked through ABP’s dynamic proxy, the following exception is thrown:

Could not find remote action for method: System.Threading.Tasks.Task1[ System.Collections.Generic.List1[Millennial.UserDetailInfos.TeamMemberDto] ] GetAllAsync() on the URL: https://localhost:44364/

Exception Stack Trace (shortened) Volo.Abp.AbpException: Could not find remote action for method: GetAllAsync()

at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.FindActionAsync at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor

What Is Confusing

The API endpoint exists

Swagger shows the endpoint

Direct HTTP GET works

But ABP dynamic proxy fails to resolve it via /api/abp/api-definition

Architecture & Configuration

44364 is the HttpApi.Host

RemoteServices:Default:BaseUrl is set to:

"RemoteServices": { "Default": { "BaseUrl": "https://localhost:44364" } }

Tiered setup is intentional

What I Have Already Tried

✔ Confirmed endpoint works directly in browser and Postman

✔ Verified Swagger shows /api/app/user-detail-info/all

✔ Restarted HttpApi.Host and PublicWeb

✔ Verified https://localhost:44364/api/abp/api-definition is accessible

✔ Confirmed routing attributes on controller:

[RemoteService] [Area("app")] [Route("api/app/user-detail-info")]

✔ Verified GetAllAsync() exists on:

AppService interface

AppService implementation

HttpApi controller

✔ Confirmed correct RemoteServices:Default:BaseUrl

✔ Confirmed the request reaches controller before exception

✔ Confirmed exception occurs after controller execution

✔ Attempted calling only from JS proxy (same behavior if resolved server-side)

✔ Clean rebuild and restart

✔ No [RemoteService(false)] applied

Expected Behavior

ABP dynamic proxy should resolve the remote action via API definition and execute the HTTP call successfully, since the endpoint exists and is reachable.

Actual Behavior

ABP dynamic proxy throws:

Could not find remote action for method GetAllAsync()

even though the endpoint exists and works.

Questions

Under what conditions does ABP dynamic proxy fail to match an existing HttpApi controller action?

Is it required that the method be exposed via conventional controllers only, even if a custom controller exists?

Can dynamic proxy resolve methods that are exposed via custom HttpApi controllers?

Is this a known limitation or expected behavior?

Workaround

Direct JS abp.ajax() or fetch calls work, but dynamic proxy cannot be used reliably for this service.

  • Template: app
  • Created ABP Studio Version: 2.1.0
  • Current ABP Studio Version: 2.1.6
  • Tiered: Yes
  • Multi-Tenancy: Yes
  • UI Framework: blazor-server
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Database Provider: ef
  • Database Management System: sqlserver
  • Separate Tenant Schema: Yes
  • Mobile Framework: none
  • Public Website: Yes
  • Social Login: Yes
  • Include Tests: Yes
  • Kubernetes Configuration: Yes
  • Distributed Event Bus: rabbitmq
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • FileManagement
    • TextTemplateManagement
    • LanguageManagement
    • AuditLogging
    • Chat
    • OpenIddictAdmin
  • Selected Languages: English, French, Spanish
  • Default Language: English
  • Create Command: abp new Millennial -t app --tiered --ui-framework blazor-server --database-provider ef --database-management-system sqlserver --theme leptonx --separate-tenant-schema --skip-migration --skip-migrator --public-website --without-cms-kit --dont-run-install-libs --dont-run-bundling -chat -file-management

3 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    Need cause: dynamic proxy uses api-definition metadata which is based on application service interfaces in Application.Contracts and their conventional HTTP API controllers in HttpApi layer. In question, they say they also created custom HttpApi controller. Key: dynamic C# proxies map method by interface & conventions; custom controllers are supported if they implement same interface & RemoteService attribute etc. But error says could not find remote action for method GetAllAsync on base URL root: that usually means this method is not in api-definition JSON of that remote service name. Reasons: service is not in Application.Contracts assembly registered in AddHttpClientProxies; RemoteServiceName mismatch; wrong remote service in client; area/route mismatch vs conventions? But api-definition is what proxy inspects. api-definition includes all controllers with [RemoteService] or implementing IApplicationService? Need more specific: in ABP 10 api-definition by default only for controllers derived from AbpController and that has [RemoteService] or implements IApplicationService or is conventional for app services. If he added HttpApi controller but removed app service from RemoteService(true)? He says app service method exists and controller. In stack they say request reaches controller before exception and exception after execution – interesting: probably dynamic proxy invoking api-definition first time, caching; but he made manual call elsewhere? Might be mixing: JS proxy works through api-definition at /api/abp/api-definition? they said it fails as well. Another thought: method is parameterless GetAllAsync returning List<TeamMemberDto>. But their controller route is GET /api/app/user-detail-info/all. Conventional naming for app service GetListAsync maps to GET /api/app/user-detail-infos; paramless GetAllAsync would map to GET /api/app/user-detail-info/team-members ? Unsure. Dynamic proxy uses method signature to find ApiDescription (HTTP method, route template, parameters). It might not match because controller action signature differs: e.g. controller action name AllAsync, or different return type, or missing Async suffix. They say controller endpoint is GET /all, but app service method GetAllAsync likely exposed conventionally as GET /all as well only if controller is for app service. However they already have custom controller with [Route("api/app/user-detail-info")] and action [HttpGet("all")] matching Task<List<TeamMemberDto>> GetAllAsync(). For dynamic proxy, what matters is interface IBlaAppService in contracts, and HttpApi.Host exposes implementation via controller that implements interface or uses [RemoteService] and [Route] etc; but crucial: api-definition groups by remote service name; custom controller's RemoteServiceName must match 'Default' or used name. They only have [RemoteService] with no RemoteServiceName, so default 'Default'. On client side, they configured AddHttpClientProxies(typeof(AppContracts).Assembly, "Public") maybe; mismatch leads to not matching. However then none of methods of that service would work; but they say other methods maybe ok? Not specified.

    Need URLs: dynamic client docs and /api-definition docs. Use UrlCheckManyAsync.

    1. Solution

    ABP’s dynamic HTTP client proxy does not look at “any endpoint that exists”.
    It only works for methods that it can map from your service interface to an entry in /api/abp/api-definition for the same remote service name, same interface, and same method signature.

    Your symptoms mean:

    • /api/app/user-detail-info/all exists and is callable directly ✔
    • But GetAllAsync is not present (or not compatible) in /api/abp/api-definition for the service/interface the proxy is using ❌
    • Therefore ApiDescriptionFinder throws: “Could not find remote action for method … GetAllAsync() …”

    Below is a checklist that fixes this for your scenario and answers your questions.


    A. Make sure the controller action is “discoverable” for dynamic proxies

    1. Controller must implement the same application service interface

    If your application service interface is:

    public interface IUserDetailInfoAppService : IApplicationService
    {
        Task<List<TeamMemberDto>> GetAllAsync();
    }
    

    then your HttpApi controller should look like:

    [RemoteService] // or [RemoteService(Name = "Default")] if you use a different name
    [Area("app")]
    [Route("api/app/user-detail-info")]
    public class UserDetailInfoController 
        : AbpController, IUserDetailInfoAppService
    {
        private readonly IUserDetailInfoAppService _appService;
    
        public UserDetailInfoController(IUserDetailInfoAppService appService)
        {
            _appService = appService;
        }
    
        [HttpGet]
        [Route("all")]
        public Task<List<TeamMemberDto>> GetAllAsync()
        {
            return _appService.GetAllAsync();
        }
    }
    

    Key point:
    Dynamic proxies map using the interface type + method signature. If the controller does not implement the same interface that your client is using, ABP cannot match it in api-definition.


    1. Method name and signature must match

    The client proxy is created for Task<List<TeamMemberDto>> GetAllAsync().

    Your controller action must have exactly:

    public Task<List<TeamMemberDto>> GetAllAsync()
    

    Changes such as:

    • Different return type (e.g. IActionResult, List<TeamMemberDto>, etc.)
    • Different name (e.g. GetAll, GetAllTeamMembersAsync)
    • Different parameters

    will cause ApiDescriptionFinder to consider it a different method and fail.


    1. Method must not be disabled with [RemoteService(false)] anywhere

    You already checked this, but confirm that:

    • The interface method is not decorated with [RemoteService(false)]
    • The application service implementation class is not decorated with [RemoteService(false)]

    If any of these exist, the method is excluded from the generated API definition.


    1. Remote service name must be consistent

    Dynamic proxies in your client web app are registered with something like:

    context.Services.AddHttpClientProxies(
        typeof(MillennialApplicationContractsModule).Assembly,
        "Default"  // or another name
    );
    

    On the server side:

    • If you use [RemoteService] with no name, the service is exposed under "Default".
    • If you use [RemoteService(Name = "Public")] (or something else), then your client must also use that same remote service name when registering AddHttpClientProxies.

    So, check:

    • The RemoteService attribute on UserDetailInfoController and/or on IUserDetailInfoAppService / UserDetailInfoAppService.
    • The remote service name supplied to AddHttpClientProxies in your PublicWeb module.

    If they are different, the dynamic proxy looks at the wrong set of actions in /api/abp/api-definition and cannot find GetAllAsync.


    1. The interface assembly must be the one you register for proxies

    Make sure IUserDetailInfoAppService is in the Application.Contracts project that you pass to AddHttpClientProxies:

    context.Services.AddHttpClientProxies(
        typeof(MillennialApplicationContractsModule).Assembly,
        "Default"
    );
    

    If the interface lives in some other assembly and that assembly is not passed into AddHttpClientProxies, ABP will generate a proxy for a different type (or none), so it won’t match.


    1. Verify that the method actually appears in /api/abp/api-definition

    From a browser, while HttpApi.Host is running, open:

    • https://localhost:44364/api/abp/api-definition?includeTypes=true

    Then search the JSON for:

    • "UserDetailInfo" or controller name
    • "TeamMemberDto"
    • "GetAllAsync"

    If GetAllAsync (or the corresponding action) is not present there, dynamic proxy can never work. Then:

    • Re-check points 1–5 above.
    • Do a Clean + Rebuild of the whole solution after changes.
    • Restart both HttpApi.Host and PublicWeb.

    B. Answers to your specific questions

    Under what conditions does ABP dynamic proxy fail to match an existing HttpApi controller action?

    It fails when any of these is true:

    • The controller action is not present (or not compatible) in /api/abp/api-definition for the target remote service.
    • The controller does not implement the same application service interface used by the client proxy.
    • The method name/parameters/return type differ between interface and controller action.
    • The service/method is disabled by [RemoteService(false)].
    • The action belongs to a different remote service name than the one the client uses.
    • The interface assembly is not registered with AddHttpClientProxies.

    Is it required that the method be exposed via conventional controllers only, even if a custom controller exists?

    No. You can use custom HttpApi controllers, but for dynamic C# proxies they must still:

    • Be marked or inferred as [RemoteService], and
    • Implement the same interface,
    • With matching method signatures.

    Can dynamic proxy resolve methods that are exposed via custom HttpApi controllers?

    Yes, as long as they satisfy the conditions above and appear correctly in /api/abp/api-definition for the relevant remote service name.


    Is this a known limitation or expected behavior?

    It is expected behavior: dynamic proxies are contract-based, not “URL-based”.
    They don’t scan “whatever routes exist”; they only use metadata from api-definition that is produced from application service contracts & [RemoteService] controllers.


    If you align:

    • IUserDetailInfoAppService (in Application.Contracts),
    • UserDetailInfoController (implementing that interface, [RemoteService], correct route),
    • Remote service name ("Default" vs custom),
    • And verify GetAllAsync is visible in /api/abp/api-definition,

    then the dynamic proxy call to GetAllAsync from your PublicWeb project will work.


    2. Sources

    • Dynamic C# client proxies and how they map to /api/abp/api-definition:
      https://docs.abp.io/en/abp/latest/API/Dynamic-CSharp-API-Clients
    • Related support question showing the same exception and controller/app service interaction:
      https://abp.io/support/questions/1735

    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.

  • User Avatar
    0
    devchase321 created

    i already check these possible solutions but it cant work

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share a demo project? I will download and check it.

    liming.ma@volosoft.com

    Thanks

Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.2.0-preview. Updated on January 09, 2026, 07:22
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.