Base solution for your next web application
Open Closed

MyAppSession Not Get Data #9982


User avatar
0
billyteng created
  • What is your product version?

  • Product Version is 10.0.0

  • What is your product type (Angular or MVC)?

  • Angular

  • What is product framework type (.net framework or .net core)?

  • .net core

  • What is ABP Framework version?

  • 6.1

I need some data to store in session which is reuse after logined.
I had override CreateAsync(User user) method in UserClaimsPrincipalFactory.cs. Look it

public override async Task CreateAsync(User user)

{
var claim = await base.CreateAsync(user);
        var resObj = (from res in _reservationRepository.GetAll()
                      join gs in _guestRepository.GetAll() on res.GuestKey equals gs.Id
                      join r in _roomRepository.GetAll() on res.RoomKey equals r.Id
                      where (res.Status == 1 || res.Status == 2) && (gs.EMail == user.EmailAddress || gs.LastName == user.UserName)
                      select new 
                      {
                          DocNo = res.DocNo,
                          ReservationKey = res.Id,
                          GuestKey = gs.Id
                      }).FirstOrDefault();
        if (resObj != null)
        {
            claim.Identities.First().AddClaim(new Claim("Application_DOCNO", resObj.DocNo));
        }

        return claim;// it is ok. Docno value have in claims.
    }

Then I created MyAppSession Class folowing :

    public class MyAppSession : ClaimsAbpSession, ITransientDependency,IMyAppSession
{
    public MyAppSession(
    IPrincipalAccessor principalAccessor,
    IMultiTenancyConfig multiTenancy,
    ITenantResolver tenantResolver,
    IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider) :
    base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
    {
    }
    public string DOCNO
    {
        get
        {
            var userDocClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "Application_DOCNO");
            if (userDocClaim == null || string.IsNullOrEmpty(userDocClaim?.Value))
            {
                return null;
            }

            return userDocClaim.Value;
        }

    }

This is IMyAppSession Interface

public interface IMyAppSession
{
string DOCNO { get; }
}

This is session value retrive class

public class TokenAuthController : BEZNgCoreControllerBase
{
private readonly IMyAppSession \_p;
public TokenAuthController(IMyAppSession p)
{
\_p = p;
}
    public string GetSession()
    {
        return _p.DOCNO;// Here value is null. Why?
    }
}

Is there anything need to change? Please help me.


18 Answer(s)
  • User Avatar
    0
    zony created
    Support Team

    Hi billyteng,
    You need to replace the default UserClaimsPrincipalFactory in the IoC container.
    Module code:

    public class YourApplicationModule : AbpModule
    {
        public override void PreInitialize()
        {
            IocManager.IocContainer.Register(
                Component
                    .For<IUserClaimsPrincipalFactory<User>, CustomClaimFactory>()
                    .LifestyleTransient()
                    .IsDefault());
        }
    }
    

    Custom session code:

    public class CustomClaimFactory : AbpUserClaimsPrincipalFactory<User, Role>
    {
        public CustomClaimFactory(AbpUserManager<Role, User> userManager,
            AbpRoleManager<Role, User> roleManager,
            IOptions<IdentityOptions> optionsAccessor) : base(userManager,
            roleManager,
            optionsAccessor)
        {
        }
    
        public override async Task<ClaimsPrincipal> CreateAsync(User user)
        {
            var claim = await base.CreateAsync(user);
    
            claim.Identities.First()
                .AddClaim(new Claim("Custom", "Hello World"));
    
            return claim;
        }
    }
    
    public interface ICustomAppSession
    {
        string Custom { get; }
    }
    
    public class CustomAppSession : ClaimsAbpSession,
        ITransientDependency,
        ICustomAppSession
    {
        public CustomAppSession(IPrincipalAccessor principalAccessor,
            IMultiTenancyConfig multiTenancy,
            ITenantResolver tenantResolver,
            IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider) : base(principalAccessor,
            multiTenancy,
            tenantResolver,
            sessionOverrideScopeProvider)
        {
        }
    
        public string Custom
        {
            get
            {
                var userDocClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "Custom");
                if (userDocClaim == null || string.IsNullOrEmpty(userDocClaim?.Value))
                {
                    return null;
                }
    
                return userDocClaim.Value;
            }
        }
    }
    
    public class TestAppService : QADemoDemoAppServiceBase
    {
        private readonly IUserClaimsPrincipalFactory<User> _claimsPrincipalFactory;
        private readonly ICustomAppSession _customAppSession;
        private readonly UserManager _userManager;
    
        public TestAppService(ICustomAppSession customAppSession,
            IUserClaimsPrincipalFactory<User> claimsPrincipalFactory,
            UserManager userManager)
        {
            _customAppSession = customAppSession;
            _claimsPrincipalFactory = claimsPrincipalFactory;
            _userManager = userManager;
        }
    
        public async Task<string> GetInfoAsync()
        {
            var user = await _userManager.GetUserByIdAsync(AbpSession.UserId.Value);
    
            var value = _customAppSession.Custom;
            var claims = await _claimsPrincipalFactory.CreateAsync(user);
            await Task.CompletedTask;
    
            return "Ok";
        }
    }
    

    Result:
    image.png

  • User Avatar
    0
    billyteng created

    Hi Zony,
    Thanks for your reply. I did your follow. But it's still null value. Not show "Hello World". Look my code.

    In Application layer
    public class NameNgCoreApplicationModule : AbpModule
    {
    public override void PreInitialize()
    {
    //Adding authorization providers
    Configuration.Authorization.Providers.Add<AppAuthorizationProvider>();

            //Adding custom AutoMapper configuration
            Configuration.Modules.AbpAutoMapper().Configurators.Add(CustomDtoMapper.CreateMappings);
    
            //For CustomClaimFactory
            IocManager.IocContainer.Register(
            Component
                .For<IUserClaimsPrincipalFactory<User>, CustomClaimFactory>()
                .LifestyleTransient()
                .IsDefault());
        }
    
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(BEZNgCoreApplicationModule).GetAssembly());
        }
    }
    

    I created "CustomClaimFactory" class in NameNgCore.Core project.

    public class CustomClaimFactory : AbpUserClaimsPrincipalFactory<User, Role>
    {
    private readonly IRepository<Guest, Guid> _guestRepository;
    private readonly IRepository<Reservation, Guid> _reservationRepository;
    private readonly IRepository<Room, Guid> _roomRepository;

        public CustomClaimFactory(AbpUserManager<Role, User> userManager,
        AbpRoleManager<Role, User> roleManager,
        IOptions<IdentityOptions> optionsAccessor,
        IRepository<Guest, Guid> guestRepository,
        IRepository<Reservation, Guid> reservationRepository,
        IRepository<Room, Guid> roomRepository
    
            ) : base(userManager,
        roleManager,
        optionsAccessor)
        {
            _guestRepository = guestRepository;
            _reservationRepository = reservationRepository;
            _roomRepository = roomRepository;
        }
        public override async Task<ClaimsPrincipal> CreateAsync(User user)
        {
            var claim = await base.CreateAsync(user);
    
            var resObj = (from res in _reservationRepository.GetAll()
                          join gs in _guestRepository.GetAll() on res.GuestKey equals gs.Id
                          join r in _roomRepository.GetAll() on res.RoomKey equals r.Id
                          where (res.Status == 1 || res.Status == 2) && (gs.EMail == user.EmailAddress || gs.LastName == user.UserName)
                          select new
                          {
                              DocNo = res.DocNo,
                              ReservationKey = res.Id,
                              GuestKey = gs.Id
                          }).FirstOrDefault();
             // resObj has value             
            if (resObj != null)
            {
                claim.Identities.First().AddClaim(new Claim("Application_DOCNO", "Hello World"));
              
            }           
    
            return claim;
        }
    }
    
    public interface IMyAppSession
    {
        string DOCNO { get; }      
    }
    

    public class MyAppSession : ClaimsAbpSession, ITransientDependency,IMyAppSession
    {
    public MyAppSession(
    IPrincipalAccessor principalAccessor,
    IMultiTenancyConfig multiTenancy,
    ITenantResolver tenantResolver,
    IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider) :
    base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
    {
    }
    public string DOCNO
    {
    get
    {
    var userDocClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "Application_DOCNO");
    if (userDocClaim == null || string.IsNullOrEmpty(userDocClaim?.Value))
    {
    return null;
    }

                return userDocClaim.Value;                
            }
    
        }
     }
     
     This is TokenAuthController in NameNgCore.Web.Core project
     which  call store values
     
      public class TokenAuthController : NameNgCoreControllerBase
    {
    private readonly IUserClaimsPrincipalFactory<User> _iclaimsPrincipalFactory;
    private readonly IMyAppSession _p;
    public TokenAuthController(IMyAppSession p,
            IUserClaimsPrincipalFactory<User> iclaimsPrincipalFactory
    )
    {
     _p = p;
            _iclaimsPrincipalFactory = iclaimsPrincipalFactory;
    }
    
     [HttpPost]
        public async Task<AuthenticateResultModel> Authenticate([FromBody] AuthenticateModel model)
        {
            your code ...ok....then.......
            var loginResult = await GetLoginResultAsync(
                model.UserNameOrEmailAddress,
                model.Password,
                GetTenancyNameOrNull()
            );
            ..........
             var refreshToken = CreateRefreshToken(await CreateJwtClaims(loginResult.Identity, loginResult.User,
                tokenType: TokenType.RefreshToken));
            var accessToken = CreateAccessToken(await CreateJwtClaims(loginResult.Identity, loginResult.User,
                refreshTokenKey: refreshToken.key));
                
            var claims = await _iclaimsPrincipalFactory.CreateAsync(loginResult.User);
    
            var d =_p.DOCNO ; // here value is null. Actually it must show "Hello World" 
            
            return new AuthenticateResultModel
            {
                AccessToken = accessToken,
                ExpireInSeconds = (int)_configuration.AccessTokenExpiration.TotalSeconds,
                RefreshToken = refreshToken.token,
                RefreshTokenExpireInSeconds = (int)_configuration.RefreshTokenExpiration.TotalSeconds,
                EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
                TwoFactorRememberClientToken = twoFactorRememberClientToken,
                UserId = loginResult.User.Id,
                ReturnUrl = returnUrl
            };
        }
    }
    
    please help me..Is there anything path?
    
  • User Avatar
    0
    zony created
    Support Team

    Hi billyteng,
    It seems that there is no problem. Can you send the sample project to info@aspnetzero.com? Please include Question-9982 in the email.

  • User Avatar
    0
    zony created
    Support Team

    It seems that the value of resObj may be Null. I suggest you check whether this code is the expected situation.

             if (resObj != null)
             {
                 claim.Identities.First().AddClaim(new Claim("Application_DOCNO", "Hello World"));
             }
    
  • User Avatar
    0
    billyteng created

    I have alread sent the files to your info@aspnetzero.com. Please check it.

  • User Avatar
    0
    zony created
    Support Team

    Thanks, I will check it.

  • User Avatar
    0
    billyteng created

    Hi Zony,

    I can't hear anything from you. Please....

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @billyteng

    Could you share your full project and steps to reproduce this problem to info@aspnetzero.com.
    I will take care of it immediately.

    Thanks,

  • User Avatar
    0
    billyteng created

    Hi @ismcagdas

    I have sent email to info@aspnetzero.com and google drive download link.

    Thanks

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @billyteng

    Thanks, I have requested access, could you allow me to download the project ?

    Thanks,

  • User Avatar
    0
    billyteng created

    Hi @ismcagdas

    Thanks reply. I have already shared with info@aspnetzero.com in google drive. Please look at it.
    Thanks

  • User Avatar
    0
    billyteng created

    HI @ismcagdas

    I have already change access permission. Now you can download it. Please....

    Thanks

  • User Avatar
    0
    billyteng created

    Hi ismcagdas,

    Any update for above problems ?

    Thanks

  • User Avatar
    0
    billyteng created

    Hi ismcagdas,

    Could you please take a look this case?

    Thanks

  • User Avatar
    0
    musa.demir created

    Hi @billyteng
    You are trying to get session value before it is initialized. Session value is null when use try to login, you can check

                var abpUser = AbpSession.ToUserIdentifier();
    

    It will also be null.
    Try to get it where session is set. For example in the logout of the same controller
    image.png.


    And implementing custom session is very simple. No need to make it complex. Check that: https://aspnetboilerplate.com/Pages/Documents/Articles\How-To\add-custom-session-field-aspnet-core


    Here are my changes for your implementation.
    image.png
    image.png
    image.png
    image.png

  • User Avatar
    0
    billyteng created

    hi musa.demir ,

    I will try and get back to you.
    Thanks

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @billyteng

    Can we close this issue ?

    Thanks,

  • User Avatar
    0
    billyteng created

    Hi ismcagdas ,

    Yes. we can close now .
    Thanks