Activities of "fordz"

To add to the answer: Do the following to have the api-only (api with no database) permissions and permission grants added. *To ensure your microservice's permissions are persisted to the central Administration database:

Reference your microservice's Application.Contracts project from the AdministrationService. This allows the central service to discover and register your permission definitions.

Rebuild the solution and restart the AdministrationService. This ensures the new permissions are loaded and can be seeded.*

Okay... I got it to work (write the permissions) with my original code. I forgot to uncomment the database config getSection lines in the module class. These were commented out originally because we don't have a database for this microservice.

in the ClientServicesQueryModule.cs

private void ConfigureCustomConnectionStringResolver(ServiceConfigurationContext context)
{
    // Register the custom connection string resolver
    // This will override the default ABP connection string resolver
    context.Services.AddTransient<IConnectionStringResolver, CustomConnectionStringResolver>();

    // Configure database connection options for strongly-typed configuration
    var configuration = context.Services.GetConfiguration();

    // Configure individual database connection options sections if needed
    // This allows for future extensibility with strongly-typed configuration
    context.Services.Configure<DatabaseConnectionOptions>("AdministrationService", 
        configuration.GetSection("DatabaseConfig:AdministrationService"));
    // context.Services.Configure<DatabaseConnectionOptions>("IdentityService", 
    //     configuration.GetSection("DatabaseConfig:IdentityService"));
    context.Services.Configure<DatabaseConnectionOptions>("AuditLoggingService", 
        configuration.GetSection("DatabaseConfig:AuditLoggingService"));
    context.Services.Configure<DatabaseConnectionOptions>("SaasService", 
        configuration.GetSection("DatabaseConfig:SaasService"));
    context.Services.Configure<DatabaseConnectionOptions>("LanguageService", 
        configuration.GetSection("DatabaseConfig:LanguageService"));
    context.Services.Configure<DatabaseConnectionOptions>("AbpBlobStoring", 
        configuration.GetSection("DatabaseConfig:AbpBlobStoring"));
}

in the Data folder.

public class ClientServicesQueryDataSeeder : ITransientDependency
{
    private readonly ILogger _logger;
    private readonly IPermissionDataSeeder _permissionDataSeeder;
    
    public ClientServicesQueryDataSeeder(IPermissionDataSeeder permissionDataSeeder,
        ILogger<ClientServicesQueryDataSeeder> logger)
    {
        _permissionDataSeeder = permissionDataSeeder;
        _logger = logger;
    }
    
    [UnitOfWork]
    public virtual async Task SeedAsync(Guid? tenantId = null)
    {
        _logger.LogInformation("Starting ClientServicesQuery permission seeding...");
    
        try
        {
            var permissions = ClientServicesQueryPermissions.GetAll();
            _logger.LogInformation("Found {PermissionCount} permissions to seed: {Permissions}", 
                permissions.Length, 
                string.Join(", ", permissions));
    
            // Grant permissions to the "admin" role
            await _permissionDataSeeder.SeedAsync(
                RolePermissionValueProvider.ProviderName,
                "admin",
                permissions,
                tenantId
            );
    
            _logger.LogInformation("Successfully seeded ClientServicesQuery permissions for admin role");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to seed ClientServicesQuery permissions");
            throw;
        }
    }
}

Thanks for the quick response.

This isn't clear... 'add the ClientServicesQueryContractsModule to the DependsOn of the IdentityService or ApplicationService or both'? This means that the Admin or Identity service has to reference the ClientServicesQueryContractsModule project. This tightly couples the to microservices!

Check the docs before asking a question: https://abp.io/docs/latest Check the samples to see the basic tasks: https://abp.io/docs/latest/samples The exact solution to your question may have been answered before, and please first use the search on the homepage.

Provide us with the following info: 🧐 Hint: If you are using the ABP Studio, you can see all the information about your solution from the configuration window, which opens when you right-click on the solution and click on the Solution Configuration button.

  • Exception message and full stack trace:
  • Steps to reproduce the issue:
  • Template: microservice
  • Created ABP Studio Version: 1.0.2
  • Current ABP Studio Version: 1.2.2
  • Multi-Tenancy: Yes
  • UI Framework: mvc
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Run Install Libs: Yes
  • Database Provider: ef
  • Database Management System: sqlserver
  • Mobile Framework: none
  • Public Website: No
  • Social Login: Yes
  • Include Tests: Yes
  • Dynamic Localization: Yes
  • Kubernetes Configuration: Yes
  • Grafana Dashboard: Yes
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • TextTemplateManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: English, English (United Kingdom), Español
  • Default Language: English
  • Create Command: abp new CloverleafCMS -t microservice --ui-framework mvc --database-provider ef --database-management-system sqlserver --theme leptonx --skip-migrator --without-cms-kit --dont-run-bundling -no-file-management -no-language-management

I have a microservice project in this solution that is api only --- it has no database. I'm having trouble getting the permissions for this service saved to the administration permissions and permissionGrants tables.

under the /Data folder I have the ClientServicesQueryDataSeeder.cs If I don't have a database for the microservice, do I need to have the following:

  • ClientServicesQueryDbContext.cs
  • ClientServicesQueryDbContextFactory.cs
  • ClientServicesQueryDatabaseMigrationEventHandler.cs
  • ClientServicesQueryRuntimeDatabaseMigrator.cs

if so, how would I configure these without a database?

Here is the code that I've added that doesn't work:

public class ClientServicesQueryDataSeeder : ITransientDependency
{
    private readonly ILogger _logger;
    private readonly IPermissionDataSeeder _permissionDataSeeder;
    
    public ClientServicesQueryDataSeeder(IPermissionDataSeeder permissionDataSeeder,
        ILogger<ClientServicesQueryDataSeeder> logger)
    {
        _permissionDataSeeder = permissionDataSeeder;
        _logger = logger;
    }
    
    [UnitOfWork]
    public virtual async Task SeedAsync(Guid? tenantId = null)
    {
        _logger.LogInformation("Starting ClientServicesQuery permission seeding...");
    
        try
        {
            var permissions = ClientServicesQueryPermissions.GetAll();
            _logger.LogInformation("Found {PermissionCount} permissions to seed: {Permissions}", 
                permissions.Length, 
                string.Join(", ", permissions));
    
            // Grant permissions to the "admin" role
            await _permissionDataSeeder.SeedAsync(
                RolePermissionValueProvider.ProviderName,
                "admin",
                permissions,
                tenantId
            );
    
            _logger.LogInformation("Successfully seeded ClientServicesQuery permissions for admin role");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to seed ClientServicesQuery permissions");
            throw;
        }
    }
}

I need guidance on how to get the permission to persist to the administration permissions databases where I do not have a database to migrate in the microservice.

Provide us with the following info: 🧐 Hint: If you are using the ABP Studio, you can see all the information about your solution from the configuration window, which opens when you right-click on the solution and click on the Solution Configuration button.

  • Template: microservice
  • Created ABP Studio Version: 1.0.2
  • Current ABP Studio Version: 1.2.2
  • Multi-Tenancy: Yes
  • UI Framework: mvc
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Run Install Libs: Yes
  • Database Provider: ef
  • Database Management System: sqlserver
  • Mobile Framework: none
  • Public Website: No
  • Social Login: Yes
  • Include Tests: Yes
  • Dynamic Localization: Yes
  • Kubernetes Configuration: Yes
  • Grafana Dashboard: Yes
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • TextTemplateManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: English, English (United Kingdom), Español
  • Default Language: English
  • Create Command: abp new CloverleafCMS -t microservice --ui-framework mvc --database-provider ef --database-management-system sqlserver --theme leptonx --skip-migrator --without-cms-kit --dont-run-bundling -no-file-management -no-language-management

We're using the microservice template and using the auth-server app for authentication. The auth-server application has been slightly modified for custom branding. We are running the authserver and microservices in Azure Kubernetes.

Here is the 'HostTenantResolveContributor.cs'

public class HostTenantResolveContributor : TenantResolveContributorBase
{
    public override async Task ResolveAsync(ITenantResolveContext context)
    {
        var currentContextAccessor = context.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
        var memberConfigService = context.ServiceProvider.GetRequiredService<IMemberConfigService>();
        
        if (memberConfigService != null)
        {
#if DEBUG
            currentContextAccessor.HttpContext.Request.Host = new HostString("auth.homefree.cloverleafcms.us"); // Set the host header to a default value for testing purposes
            //currentContextAccessor.HttpContext.Request.Path = new PathString("/Account/Login"); // Set the path to root for testing purposes
#endif
            string? prefix = currentContextAccessor?.HttpContext?.Request?.GetPrefixFromHost();
            Console.WriteLine($"Tenant prefix after GetPrefixFromHost is: {prefix}.");
            if (!string.IsNullOrEmpty(prefix) && prefix != "admin")
            {
                var responseDto = await memberConfigService.GetMemberConfigByUrlPrefixAsync(prefix);
    
                if (responseDto != null && responseDto.Success)
                {
                    var member = responseDto.MemberConfig;
                    context.TenantIdOrName = member?.Id.ToString();
                    Console.WriteLine($"Member found for prefix: {prefix}");
                    Console.WriteLine($"MemberId: {member?.Id.ToString()}");
                }
                else
                {
                    Console.WriteLine($"Member not found for prefix: {prefix}. See details: {responseDto?.ErrorResponse?.Error?.Message}");
                    context.TenantIdOrName = null;
                }
                return;
            }
            else
            {
                Console.WriteLine("Tenant prefix not found in the host.");
                context.TenantIdOrName = null;
            }
        }
        else
        {
            Console.WriteLine("MemberConfigService is not available.");
            context.TenantIdOrName = null;
        }
    }

    public override string Name => "Host";

}

Here is the GetPrefixFromHost.cs extension

public static class HttpRequestExtensions
{
    public static string? GetPrefixFromHost(this HttpRequest request)
    {
        if (request?.Host.HasValue != true)
        {
            return "invalid";
        }
        string host = request.Host.Host;
        try
        {
            // Check for localhost
            if (host.Contains("localhost"))
                return null;
            if (host.Contains("host.docker.internal"))
                return null;
            // Split the host into parts
            var parts = host.Split('.');
            
            if (parts.Length < 2)
                return null;
        
            var first = parts[0];
            var second = parts[1];
        
            if (second.Equals("admin", StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("Admin subdomain detected, returning null for prefix.");
                return null;
            }
        
            if (first.Equals("auth", StringComparison.OrdinalIgnoreCase) && parts.Length >= 3)
            {
                // Return the second part as prefix
                Console.WriteLine($"Member subdomain detected, returning {parts[1]} for prefix.");
                return parts[1];
            }
        
            return "invalid"; // Return "invalid" for other cases
        }
        catch
        {
            // Return "invalid" for invalid URLs
            return "invalid";
        }
    }
}

Okay... I think we found it. Here is my curl snippet.

There was an extra '}' at the end of the Bearer Token.

The GET Postman Authorization tab looked like this:

I removed the extra '}" and the GET returned data. Thanks for help.

Project shared... GitHub invite sent.

Check the docs before asking a question: https://abp.io/docs/latest Check the samples to see the basic tasks: https://abp.io/docs/latest/samples The exact solution to your question may have been answered before, and please first use the search on the homepage.

Provide us with the following info: 🧐 Hint: If you are using the ABP Studio, you can see all the information about your solution from the configuration window, which opens when you right-click on the solution and click on the Solution Configuration button.

  • Template: microservice
  • Created ABP Studio Version: 1.0.1
  • Current ABP Studio Version: 1.0.1
  • Multi-Tenancy: Yes
  • UI Framework: mvc
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Run Install Libs: Yes
  • Database Provider: ef
  • Database Management System: sqlserver
  • Mobile Framework: none
  • Public Website: No
  • Social Login: Yes
  • Include Tests: Yes
  • Dynamic Localization: Yes
  • Kubernetes Configuration: Yes
  • Grafana Dashboard: Yes
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • TextTemplateManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: English, English (United Kingdom), Español
  • Default Language: English
  • Create Command: abp new CloverleafCMS -t microservice --ui-framework mvc --database-provider ef --database-management-system sqlserver --theme leptonx --skip-migrator --without-cms-kit --dont-run-bundling -no-file-management -no-language-management

6/23/2025 8:23:51 PM [Information] "Bearer" was not authenticated. Failure message: "IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey, KeyId: '4C44506B63683FAFB81F426A6A1225833F2BE6A8', InternalId: 'TERQa2NoP6-4H0JqahIlgz8r5qg'. , KeyId: 4C44506B63683FAFB81F426A6A1225833F2BE6A8 '. Number of keys in TokenValidationParameters: '0'. Number of keys in Configuration: '2'. Matched key was in 'Configuration'. kid: '4C44506B63683FAFB81F426A6A1225833F2BE6A8'. Exceptions caught: 'PII of type 'System.Text.StringBuilder' is hidden. For more details, see [https://aka.ms/IdentityModel/PII.]'. token: 'PII of type 'Microsoft.IdentityModel.JsonWebTokens.JsonWebToken' is hidden. For more details, see [https://aka.ms/IdentityModel/PII.]'. See https://aka.ms/IDX10511 for details." 6/23/2025 8:23:51 PM [Information] Authorization failed. "These requirements were not met: PermissionRequirement: ActionItemService.ActionItems" 6/23/2025 8:23:51 PM [Information] AuthenticationScheme: "Bearer" was challenged. 6/23/2025 8:23:51 PM [Information] Request finished "HTTP/1.1" "GET" "http"://"localhost:44379""""/api/actionitem/action-items""?clientId=10BECE0B-086C-F92C-A6D1-3A1AB084E5A2" - 401 0 null 3.5956ms

  • Steps to reproduce the issue:
  • using v9.2 and Abp Studio create a microservice solution.
    • add a business microservice and a Token microservice to get an abp token for calling the business microservice. Ours are ActionItemService and TokenService.
    • using the MVC web app add a client called 'CloverleafApi' or anyname you like or add the following to
      • OpenIddictDataSeeder.cs - add the application -
        • //Cloverleaf API Client await CreateOrUpdateApplicationAsync( applicationType: OpenIddictConstants.ApplicationTypes.Web, name: "CloverleafAPI", type: OpenIddictConstants.ClientTypes.Confidential, consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "Cloverleaf API Client", secret: "XXXXx", // replace with your secret grantTypes: new List //Hybrid flow { OpenIddictConstants.GrantTypes.ClientCredentials, OpenIddictConstants.GrantTypes.Password, OpenIddictConstants.GrantTypes.RefreshToken }, scopes: commonScopes.Union(new[] { "ActionItemService", "AdministrationService", "AuditLoggingService", "AuthServer", "GdprService", "IdentityService", "LanguageService", "SaasService", "TokenService", }).ToList(), redirectUris: null, postLogoutRedirectUris: null, clientUri: null, logoUri: null );

Once solution is running in AbpStudio then go to Postman and get a token via the TokenService using the host admin id and password. Create an ActionItem. Update and ActionItem. Get the ActionItem. I can successfully create and update an ActionItem with the host admin credentials but I get the above 401 not authorized when calling the GET endpoint.

I have the following version of Abp Studio:

Abp Studio crashes when I open my Abp Solution file. The solution will load and after a few seconds the Abp Studio app will crash.

Here is the error log: 2025-04-22 16:23:49.781 -05:00 [WRN] The process cannot access the file 'C:\Users\xxxxx\source\repos\CloverleafCMS-Microservices-Abp-1.abpstudio\state.json' because it is being used by another process. System.IO.IOException: The process cannot access the file 'C:\Users\xxxxx\source\repos\CloverleafCMS-Microservices-Abp-1.abpstudio\state.json' because it is being used by another process. at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options) at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable1 unixCreateMode) at System.IO.File.OpenHandle(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) at System.IO.File.WriteToFileAsync(String path, FileMode mode, ReadOnlyMemory1 contents, Encoding encoding, CancellationToken cancellationToken) at Volo.Abp.Studio.UI.Solutions.SolutionState.SolutionStateSynchronizer.CilggAsHIm(String ) at Volo.Abp.Studio.UI.Solutions.SolutionState.SolutionStateSynchronizer.<>c__DisplayClass26_0.DDK1Yhg0gnvQQJBxeNZ.MoveNext() --- End of stack trace from previous location --- at System.Threading.Tasks.Task.<>c.b__128_0(Object state) at Avalonia.Threading.SendOrPostCallbackDispatcherOperation.InvokeCore() at Avalonia.Threading.DispatcherOperation.Execute() at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation job) at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean fromExplicitBackgroundProcessingCallback) at Avalonia.Threading.Dispatcher.Signaled() at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG& lpmsg) at Avalonia.Win32.Win32DispatcherImpl.RunLoop(CancellationToken cancellationToken) at Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl) at Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken) at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args) at ktmpmYYhNMEr3TNPigT.jGyPv8YNF0HevUNmIxp.rf7YgLwjGG(String[] )

I'm starting the Abp Studio with administrator privileges, but it still trips the following error: The process cannot access the file 'C:\Users\xxxxx\source\repos\CloverleafCMS-Microservices-Abp-1.abpstudio\state.json' because it is being used by another process.

Thanks for the local Kubernetes test. Still I think a test via a deployed application to an Azure Kubernetes service would be a better comparison to our situation. One question still.... do you (Abp.io) have any production clients that are running abpFramework microservices template in an Azure Kubernetes Service? If so, can we find out what there metrics are for obtaining a token?

Showing 1 to 10 of 27 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 18, 2025, 07:10