Activities of "isaac.yip@cpy.com.hk"

  • ABP Framework version: v5.2.1
  • UI type: Blazor
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): Microservice Pro Template
  • Exception message and stack trace: Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync()
  • Steps to reproduce the issue:"
  1. Add a new microservice solution followed the steps in https://docs.abp.io/en/commercial/latest/startup-templates/microservice/add-microservice
  2. Called the SampleAppService GetAsync method and throw exceptions.

If we change to static Client Proxies using the CLI abp generate-proxy -t csharp -u https://localhost:44741 -m NotificationService which https://localhost:44741 is new NotificationService, problem can be solved.

[DependsOn(
    typeof(NotificationServiceApplicationContractsModule),
    typeof(AbpHttpClientModule))]
public class NotificationServiceHttpApiClientModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddStaticHttpClientProxies(typeof(NotificationServiceApplicationContractsModule).Assembly,
            NotificationServiceRemoteServiceConsts.RemoteServiceName);

        // context.Services.AddHttpClientProxies(
        //     typeof(NotificationServiceApplicationContractsModule).Assembly,
        //     NotificationServiceRemoteServiceConsts.RemoteServiceName
        // );

        Configure<AbpVirtualFileSystemOptions>(options =>
        {
            options.FileSets.AddEmbedded<NotificationServiceHttpApiClientModule>();
        });
    }
}

Sine the generated templated using dynamic proxy, can we use dynamic Client Proxies?

abp new NotificationService -t microservice-service-pro

if using dynamic proxying with the ocelot, it will throw a exception : Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync()

ocelot.json

{
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:44325"
  },
  "Routes": [
    {
      "ServiceKey": "Account Service",
      "DownstreamPathTemplate": "/api/account/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44322
        }
      ],
      "UpstreamPathTemplate": "/api/account/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Identity Service",
      "DownstreamPathTemplate": "/api/identity/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44388
        }
      ],
      "UpstreamPathTemplate": "/api/identity/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Identity Service",
      "DownstreamPathTemplate": "/api/identity-server/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44388
        }
      ],
      "UpstreamPathTemplate": "/api/identity-server/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Identity Service",
      "DownstreamPathTemplate": "/api/account-admin/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44388
        }
      ],
      "UpstreamPathTemplate": "/api/account-admin/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Saas Service",
      "DownstreamPathTemplate": "/api/saas/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44381
        }
      ],
      "UpstreamPathTemplate": "/api/saas/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/abp/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/abp/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/audit-logging/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/audit-logging/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/language-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/language-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/text-template-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/text-template-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/feature-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/feature-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/permission-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/permission-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/setting-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/setting-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Administration Service",
      "DownstreamPathTemplate": "/api/lepton-theme-management/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44367
        }
      ],
      "UpstreamPathTemplate": "/api/lepton-theme-management/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Product Service",
      "DownstreamPathTemplate": "/api/product-service/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44361
        }
      ],
      "UpstreamPathTemplate": "/api/product-service/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Client Service",
      "DownstreamPathTemplate": "/api/client-service/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 45304
        }
      ],
      "UpstreamPathTemplate": "/api/client-service/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    {
      "ServiceKey": "Notification Service",
      "DownstreamPathTemplate": "/api/notification-service/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44741
        }
      ],
      "UpstreamPathTemplate": "/api/notification-service/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    }
  ]  
}

SampleController.cs

[RemoteService(Name = "NotificationService")]
[Area("notificationService")]
[ControllerName("NotificationService")]
[Route("api/notification-service/sample")]
public class SampleController : NotificationServiceController, ISampleAppService
{
    private readonly ISampleAppService _sampleAppService;

    public SampleController(ISampleAppService sampleAppService)
    {
        _sampleAppService = sampleAppService;
    }

    [HttpGet]
    public async Task<SampleDto> GetAsync()
    {
        return await _sampleAppService.GetAsync();
    }

    [HttpGet]
    [Route("authorized")]
    public async Task<SampleDto> GetAuthorizedAsync()
    {
        return await _sampleAppService.GetAsync();
    }
}
  • ABP Framework version: v5.2.1
  • UI type: Blazor
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace:
  • Steps to reproduce the issue:"

How to render the latest Text templating content?

After editing the TextTemplate content, we use the _templateRenderer.RenderAsync method which return the default content.

Which method should we use to get the updated content?

Added but still not working.

The API can be found in gateway Swagger UI and use postman to test is work. https://localhost:44325/api/notification-service/sample

But calling the method from blazor will return:

Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync() on the URL: https://localhost:44325/

port 44325 is the gateway port

<Project Sdk="Microsoft.NET.Sdk.Web">

    <Import Project="..\..\..\..\common.props" />

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <ProjectReference Include="..\..\..\..\shared\MOS.Shared.Hosting.Gateways\MOS.Shared.Hosting.Gateways.csproj" />
        <ProjectReference Include="..\..\..\..\services\notification\src\MOS.NotificationService.HttpApi\MOS.NotificationService.HttpApi.csproj" /> 
    </ItemGroup>

    <ItemGroup>
        <Compile Remove="Logs\**" />
        <Content Remove="Logs\**" />
        <EmbeddedResource Remove="Logs\**" />
        <None Remove="Logs\**" />
    </ItemGroup>

</Project>
[DependsOn(
    typeof(MOSSharedHostingGatewaysModule),
    typeof(NotificationServiceHttpApiModule)
)]
public class MOSWebGatewayModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        // Enable if you need hosting environment
        // var hostingEnvironment = context.Services.GetHostingEnvironment();
        var configuration = context.Services.GetConfiguration();
        var hostingEnvironment = context.Services.GetHostingEnvironment();

        SwaggerConfigurationHelper.ConfigureWithAuth(
            context: context,
            authority: configuration["AuthServer:Authority"],
            scopes: new
                Dictionary<string, string> /* Requested scopes for authorization code request and descriptions for swagger UI only */ {
                    { "AccountService", "Account Service API" },
                    { "IdentityService", "Identity Service API" },
                    { "AdministrationService", "Administration Service API" },
                    { "SaasService", "Saas Service API" },
                    { "ProductService", "Product Service API" },
                    { "ClientService", "Client Service API" },
                    { "NotificationService", "Notification Service API" }
                },
            apiTitle: "Web Gateway API"
        );

        context.Services.AddCors(options =>
        {
            options.AddDefaultPolicy(builder =>
            {
                builder
                    .WithOrigins(
                        configuration["App:CorsOrigins"]
                            .Split(",", StringSplitOptions.RemoveEmptyEntries)
                            .Select(o => o.Trim().RemovePostFix("/"))
                            .ToArray()
                    )
                    .WithAbpExposedHeaders()
                    .SetIsOriginAllowedToAllowWildcardSubdomains()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
            });
        });
    }

    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCorrelationId();
        app.UseCors();
        app.UseSwagger();
        app.UseSwaggerUI(options =>
        {
            var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
            var routes = configuration.GetSection("Routes").Get<List<OcelotConfiguration>>();
            var routedServices = routes
                .GroupBy(t => t.ServiceKey)
                .Select(r => r.First())
                .Distinct();

            foreach (var config in routedServices.OrderBy(q => q.ServiceKey))
            {
                var url = $"{config.DownstreamScheme}://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}:{config.DownstreamHostAndPorts.FirstOrDefault()?.Port}";
                if (!env.IsDevelopment())
                {
                    url = $"https://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}";
                }

                options.SwaggerEndpoint($"{url}/swagger/v1/swagger.json", $"{config.ServiceKey} API");
                options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
            }
        });
        app.UseAbpSerilogEnrichers();
        app.UseRewriter(new RewriteOptions()
            // Regex for "", "/" and "" (whitespace)
            .AddRedirect("^(|\\|\\s+)$", "/swagger"));
        app.UseOcelot().Wait();
    }
}
  1. Update the content in Text Templates Section

  2. Call the render function

text = await TemplateRenderer.RenderAsync("Abp.Account.EmailSecurityCode",
                new
                {
                    code = 1234
                });

blazor log:

2022-04-28 16:23:00.480 +08:00 [INF] Start processing HTTP request GET "https://localhost:44325/api/abp/api-definition"
2022-04-28 16:23:00.481 +08:00 [INF] Sending HTTP request GET "https://localhost:44325/api/abp/api-definition"
2022-04-28 16:23:00.678 +08:00 [INF] Received HTTP response headers after 197.4185ms - 200
2022-04-28 16:23:00.678 +08:00 [INF] End processing HTTP request after 198.2306ms - 200
2022-04-28 16:23:00.694 +08:00 [WRN] Unhandled exception rendering component: Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync() on the URL: https://localhost:44325/
Volo.Abp.AbpException: Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync() on the URL: https://localhost:44325/
   at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.FindActionAsync(HttpClient client, String baseUrl, Type serviceType, MethodInfo method)
   at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1.GetActionApiDescriptionModel(IAbpMethodInvocation invocation)
   at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at MOS.NotificationService.Blazor.Pages.NotificationService.Test.SendEmail() in C:\Users\isaac.yip\Desktop\MOS\MOS_20220420\services\notification\src\MOS.NotificationService.Blazor\Pages\NotificationService\Test.razor.cs:line 52
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Radzen.Blazor.RadzenButton.OnClick(MouseEventArgs args)
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2022-04-28 16:23:00.699 +08:00 [ERR] Unhandled exception in circuit '6PBxuosO4MUMXMmuyj7DgkoJVB-SLUH8afvlBwE4kl8'.
Volo.Abp.AbpException: Could not found remote action for method: System.Threading.Tasks.Task`1[MOS.NotificationService.Samples.SampleDto] GetAsync() on the URL: https://localhost:44325/
   at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.FindActionAsync(HttpClient client, String baseUrl, Type serviceType, MethodInfo method)
   at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1.GetActionApiDescriptionModel(IAbpMethodInvocation invocation)
   at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at MOS.NotificationService.Blazor.Pages.NotificationService.Test.SendEmail() in C:\Users\isaac.yip\Desktop\MOS\MOS_20220420\services\notification\src\MOS.NotificationService.Blazor\Pages\NotificationService\Test.razor.cs:line 52
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Radzen.Blazor.RadzenButton.OnClick(MouseEventArgs args)
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2022-04-28 16:23:00.776 +08:00 [INF] Executed endpoint '/_blazor'
2022-04-28 16:23:00.777 +08:00 [INF] Request finished HTTP/1.1 GET https://localhost:44314/_blazor?id=pczk1P-5gdFs1D621NRtHA - - - 101 - - 68037.4493ms

web-gateway log:

2022-04-28 16:23:00.490 +08:00 [INF] Request starting HTTP/1.1 GET https://localhost:44325/api/abp/api-definition - -
2022-04-28 16:23:00.490 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: ocelot pipeline started
2022-04-28 16:23:00.490 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: Upstream url path is /api/abp/api-definition
2022-04-28 16:23:00.490 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: downstream templates are /api/abp/{everything}
2022-04-28 16:23:00.491 +08:00 [INF] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: EndpointRateLimiting is not enabled for /api/abp/{everything}
2022-04-28 16:23:00.491 +08:00 [INF] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: No authentication needed for /api/abp/api-definition
2022-04-28 16:23:00.491 +08:00 [INF] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: /api/abp/{everything} route does not require user to be authorized
2022-04-28 16:23:00.491 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: Downstream url is https://localhost:44367/api/abp/api-definition
2022-04-28 16:23:00.677 +08:00 [INF] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: 200 (OK) status code, request uri: https://localhost:44367/api/abp/api-definition
2022-04-28 16:23:00.677 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: setting http response message
2022-04-28 16:23:00.677 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: no pipeline errors, setting and returning completed response
2022-04-28 16:23:00.677 +08:00 [DBG] requestId: 0HMH8U0DU0PFU:00000002, previousRequestId: no previous request id, message: ocelot pipeline finished
2022-04-28 16:23:00.678 +08:00 [INF] Request finished HTTP/1.1 GET https://localhost:44325/api/abp/api-definition - - - 200 54537 application/json;+charset=utf-8 188.1015ms

microservice no request made here

I create a new project with microservice template, blazor ui and the problem still here.

Are you using microservice template and blazor ui?

Can you call the sample endpoint on gateway from the URL: https://localhost:44325/api/notification-service/sample ?

Can

If so, try adding the [Route] attribute to GetAsync method in SampleController:

Added. And throw the same exception.

It works now. Thank you.

Showing 1 to 10 of 18 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11