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:

  • 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&lt;IUserClaimsPrincipalFactory&lt;User&gt;, 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&lt;Role, User&gt; userManager,
        AbpRoleManager&lt;Role, User&gt; roleManager,
        IOptions&lt;IdentityOptions&gt; optionsAccessor,
        IRepository&lt;Guest, Guid&gt; guestRepository,
        IRepository&lt;Reservation, Guid&gt; reservationRepository,
        IRepository&lt;Room, Guid&gt; roomRepository
    
            ) : base(userManager,
        roleManager,
        optionsAccessor)
        {
            _guestRepository = guestRepository;
            _reservationRepository = reservationRepository;
            _roomRepository = roomRepository;
        }
        public override async Task&lt;ClaimsPrincipal&gt; 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&lt;User&gt; _iclaimsPrincipalFactory;
    private readonly IMyAppSession _p;
    public TokenAuthController(IMyAppSession p,
            IUserClaimsPrincipalFactory&lt;User&gt; iclaimsPrincipalFactory
    )
    {
     _p = p;
            _iclaimsPrincipalFactory = iclaimsPrincipalFactory;
    }
    
     [HttpPost]
        public async Task&lt;AuthenticateResultModel&gt; 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 [email protected]? 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 [email protected]. 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 [email protected]. I will take care of it immediately.

    Thanks,

  • User Avatar
    0
    billyteng created

    Hi @ismcagdas

    I have sent email to [email protected] 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 [email protected] 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 .


    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.

  • 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