Activities of "alirizaadiyahsi"

Hi @muhammedaltug, your advice worked for me. It should be in Microservice documentation.

  • ABP Framework version: v5.2.2
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no, Microservice

Identity API

I am customizing Identity module according to this document: Customizing the Application Modules I extended IdentityRoles service/repository/contoller so I have a method _roleService.GetListByIds(Guid[] ids). Everything is ok, so far. The end-point is working like expected.

Identity Angular

Question: I am creating ng-library for my each microservice to generate proxies, separately (reference:Microservice Proxy Generation). To use my new method that is in IdentityRoleService, should I create an ng-library for identity and generate identity proxies in it? So, as I understand, I will use these proxies instead of using them from abp/ng.core?

Any suggestion would be appreciated! Thanks...

Hi @liangshiwei, actually I am extending/overriding the end-point in identity-service microservice itself. And it is different then yours.

But yes it doesn't matter. I got your your point. I just ask for better way. Using RestService can be solution. Now, I created a library for identity and generated proxies in it.

I just have concerns about using it this way, if there are drawbacks.

  • ABP Framework version: v5.2.2
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): microservice/angular
EventHandler Implementation
public class AccessRequestApprovedHandler : IDistributedEventHandler<AccessRequestApprovedEto>, ITransientDependency
{
    private readonly IdentityUserManager _userManager;
    private readonly ICustomIdentityRoleRepository _customIdentityRoleRepository;
    private readonly ILogger<AccessRequestApprovedHandler> _logger;

    public AccessRequestApprovedHandler(IdentityUserManager userManager, ICustomIdentityRoleRepository customIdentityRoleRepository, ILogger<AccessRequestApprovedHandler> logger)
    {
        _userManager = userManager;
        _customIdentityRoleRepository = customIdentityRoleRepository;
        _logger = logger;
    }

    [UnitOfWork]
    public async Task HandleEventAsync(AccessRequestApprovedEto eventData)
    {
        try
        {
            var user = await _userManager.GetByIdAsync(eventData.UserId);
            var roles = await _customIdentityRoleRepository.GetListByIdsAsync(eventData.RoleIds);
            
            // Exception is thrown here.
            var identityResult = await _userManager.SetRolesAsync(user, roles.Select(r => r.Name).ToArray());
            if (!identityResult.Succeeded)
            {
                _logger.LogError($"Error occured while setting roles for user: {user.UserName}");
                foreach (var error in identityResult.Errors)
                {
                    _logger.LogError($"Error: {error.Code} - {error.Description}");
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}

Exception Message (even though I am using UnitOfWork attribute) : A DbContext can only be created inside a unit of work!

   at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider`1.GetDbContextAsync()
   at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.EnsureCollectionLoadedAsync[TProperty](TEntity entity, Expression`1 propertyExpression, CancellationToken cancellationToken)
   at Volo.Abp.Domain.Repositories.RepositoryExtensions.EnsureCollectionLoadedAsync[TEntity,TKey,TProperty](IBasicRepository`2 repository, TEntity entity, Expression`1 propertyExpression, CancellationToken cancellationToken)
   at Volo.Abp.Identity.IdentityUserStore.AddToRoleAsync(IdentityUser user, String normalizedRoleName, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Identity.UserManager`1.AddToRolesAsync(TUser user, IEnumerable`1 roles)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Volo.Abp.Identity.IdentityUserManager.SetRolesAsync(IdentityUser user, IEnumerable`1 roleNames)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Daisy.IdentityService.EventHandlers.AccessRequests.AccessRequestApprovedHandler.HandleEventAsync(AccessRequestApprovedEto eventData) in C:\Users\aliriza\Documents\Projects\GitHub\Daisy\services\identity\src\Daisy.IdentityService.Application\EventHandlers\AccessRequests\AccessRequestApprovedHandler.cs:line 34

BTW, here is repo method implementation:

    public async Task<List<IdentityRole>> GetListByIdsAsync(Guid[] ids, CancellationToken cancellationToken = default)
    {
        var query = await GetQueryableAsync();
        query = query.Where(r => ids.Contains(r.Id)).OrderBy(x => x.Name);
        return await query.ToListAsync(cancellationToken);
    }

I think it is coming from here: UnitOfWorkDbContextProvider.cs. it seems it can not use the current unit of work.

IdentityUserManager - SetRolesAsync - AddToRolesAsync - userRoleStore.AddToRoleAsync - UserRepository.EnsureCollectionLoadedAsync - GetDbContextAsync() - _dbContextProvider.GetDbContextAsync()

UPDATE:

I also try IUnitOfWorkEnable interface or inherite from ApplicationService but no luck.

It is only working when I manage uow manually. Following is working:

public async Task HandleEventAsync(AccessRequestApprovedEto eventData)
    {
        _logger.LogInformation("Event name: {@eventName}. User id: {@userId}. Role ids: {@roleIds}", AccessRequestConsts.EventNames.Approved, eventData.UserId, eventData.RoleIds);
        using var uow = _unitOfWorkManager.Begin();
        var user = await _userManager.GetByIdAsync(eventData.UserId);
        var roles = await _customIdentityRoleRepository.GetListByIdsAsync(eventData.RoleIds);
        var identityResult = await _userManager.SetRolesAsync(user, roles.Select(r => r.Name).ToArray());
        if (!identityResult.Succeeded)
        {
            _logger.LogError($"Error occured while setting roles for user: {user.UserName}");
            foreach (var error in identityResult.Errors)
            {
                _logger.LogError($"Error: {error.Code} - {error.Description}");
            }
        }

        await uow.CompleteAsync();
    }

But I cant understand why [UnitOfWork] attribute is not working?

It worked. Thanks @maliming.

  • ABP Framework version: v5.3.0
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): Angular Microservice

I added a new microservice that named FileManagerService and added database blob storing to it by using this command: abp add-module Volo.Abp.BlobStoring.Database.

All looks fine but when I trying to save files, provider is using AdminstrationServiceDB.

[Authorize(FileManagerServicePermissions.FileManager.Files.FilesDefault)]
public class FileAppService : ApplicationService, IFileAppService
{
    private IBlobContainer _fileContainer;
    private readonly IBlobContainerFactory _blobContainerFactory;

    public FileAppService(IBlobContainerFactory blobContainerFactory)
    {
        _blobContainerFactory = blobContainerFactory;
    }

    public async Task<BlobDto> GetBlobAsync(GetBlobRequestDto input)
    {
        var blob = await _fileContainer.GetAllBytesAsync(input.Name);

        return new BlobDto
        {
            Name = input.Name,
            Content = blob
        };
    }

    [Authorize(FileManagerServicePermissions.FileManager.Files.Create)]
    [Authorize(FileManagerServicePermissions.FileManager.Files.Edit)]
    public async Task SaveBlobAsync(CreateBlobInput input)
    {
        _fileContainer = _blobContainerFactory.Create("microservice-name");
        await _fileContainer.SaveAsync(input.Name, input.Content, true);
    }

How I configure blobContainer to use file-manager connection string, instead of using administration-service connection string?

And this is the file-manager-service connection strings in appsettings.json.

And DB

Hi @maliming I can't understand what you mean. I have no connection issues, actually. Each microservice can connect to its own DB via repos without issue. The problem is blobProvider is bypassing fileManagerConnectionString by administration-service. Repositories that are in blobProvider is connecting the administration service DB.

I think I should configure blobStoringProvider to connect file-manager-service DB, but I can't find any solution about this.

BTW, here is my connections:

  • ABP Framework version: v5.3.0
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): Microservice

I have following two entities:

public class FunctionalPosition : FullAuditedAggregateRoot<Guid>, IMultiTenant and public class AccessRequest : FullAuditedEntity<Guid>, IMultiTenant

DomainService for FunctionalPosition

DomainService for AccessRequest

FunctionalPosition Table

AccessRequest Table

FunctionalPosition and AccessRequest are in the same microservice and DB, but there is wrong with AccessRequest to set user and tenant. Also I am checking by debugging both client and server has the current tenant/user information. Am I missing something?

Hi @maliming, I removed blobStoring from project. We will no longer use this.

Thanks for your helping and your time.

Hi @maliming another silly mistake :) I did not check after Rider created auto-generated code.

Thanks.

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