Base solution for your next web application
Open Closed

DATA FILTER IN SESSION URGENT #3727


User avatar
0
hasan created

Dear Team,

We are using Data Filter as per the document <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Data-Filters">http://www.aspnetboilerplate.com/Pages/ ... ta-Filters</a>

I would like to read and set the DataFilter Parameter from the Session. The value will be set in two places

  1. USER LOGIN TO THE APPLICATION
  2. CHANGE THE VALUE FROM THE COMBO BOX WHICH HAS BEEN ON THE TOP OF THE PAGE.

I have configured ONMODELCREATING as per the DOCUMENT

modelBuilder.Filter("ConnectFilter", (IOrganization entity, int oid) => entity.Oid == oid, 0);

and I have modified in Initialize Method as below

this.SetFilterScopedParameterValue("ConnectFilter", "oid",1);

First Question is

Now, the value 1 in the Initialize method is hard coded for the time being. I would like to get it from Session. How to do that? How can I add my own variable in the Session?

Second Question is The filters are working perfectly for hard coded value 1. When I am saving into the Entity, it is going as 0, Do I need to modify in any another place?

Thanks


23 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    Are you using ASP.NET Core or MVC 5.x version ?

    Thanks.

  • User Avatar
    0
    hasan created

    MVC 5.X AngularJS 1.X

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    Sorry for the delay.

    You can override the Initialize method of your dbContext, call base's Initialize first and then add your parameter value like this <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/src/Abp.EntityFramework/EntityFramework/AbpDbContext.cs#L186">https://github.com/aspnetboilerplate/as ... xt.cs#L186</a>

    You need to use your custom session object here.

    You can define your custom session like this: <a class="postlink" href="https://gist.github.com/hikalkan/67469e05475c2d18cb88">https://gist.github.com/hikalkan/67469e05475c2d18cb88</a>

    Thanks.

  • User Avatar
    0
    hasan created

    Thanks for the Answer

    How to get the Custom Session Property and set it in Context Initialize Method.

    For Example, I have to set it in

    public override void Initialize()
            {
                base.Initialize();
                this.SetFilterScopedParameterValue("ConnectFilter", "oid", 1);
            }
    

    and my session is

    public class ConnectSession : ITransientDependency
        {
            public int Location { get; set; }
        }
    
        [AbpAuthorize]
        public class SessionAppService : DineConnectAppServiceBase, ISessionAppService
        {
    
            private readonly ConnectSession _mySession;
    
            public SessionAppService(ConnectSession mySession)
            {
                _mySession = mySession;
            }
    
            [DisableAuditing]
            public async Task<GetCurrentLoginInformationsOutput> GetCurrentLoginInformations()
            {
                var output = new GetCurrentLoginInformationsOutput
                {
                    User = (await GetCurrentUserAsync()).MapTo<UserLoginInfoDto>()
                };
    
                bool mutlipleUomAllowed = false;
                if (PermissionChecker.IsGranted("Pages.Tenant.House.Transaction.MultipleUOMAllowed"))
                {
                    mutlipleUomAllowed = true;
                }
    
                output.User.MultipleUomEntryAllowed = mutlipleUomAllowed;
    
                output.User.LocationRefId = GetCurrentUserLocationAsync();
    
                output.Location = (await GetLocationInfo(output.User.LocationRefId)).MapTo<LocationListDto>();
                
                if (AbpSession.TenantId.HasValue)
                {
                    output.Tenant = (await GetCurrentTenantAsync()).MapTo<TenantLoginInfoDto>();
                }
    
                return output;
            }
        }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    You need to first define your custom Session defined in this example <a class="postlink" href="https://gist.github.com/hikalkan/67469e05475c2d18cb88">https://gist.github.com/hikalkan/67469e05475c2d18cb88</a> (MyAppSession.cs).

    Then you need to set it's value in AccountController and then you can inject your new session (MyAppSession) or you can resolve it using IocContainer in the place you want to use.

    Thanks.

  • User Avatar
    0
    hasan created

    You have not answered for the first question

    How to get the session value in the context class Initialize method ?

    The DATA FILTER values are setting in the Intialize method as per your document

    Please let me know

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    You can check the usage of AbpSession in AbpDbContext here <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp.EntityFramework/EntityFramework/AbpDbContext.cs">https://github.com/aspnetboilerplate/as ... Context.cs</a>. Property injection is used here, so if you apply same method to your DbContext, you can get values from your custom session.

    Thanks.

  • User Avatar
    0
    hasan created

    Got it How to set the Value into the Property of Custom Session?

    Please let me know. It will be really helpful.

    I need to set the Property based on Combo Value Change. I can call the Session Service to do that.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    You can check on the we for changing a claim value from any part of your app. I don't remember how to do it exactly. I'm sure you can find it on the web easily.

    If you change the claim value, your session will get the new value.

    Thanks.

  • User Avatar
    0
    hasan created

    Thanks

    One last question

    1. It is perfectly working in Filtering the Entities. The Filter is getting set properly and getting proper result but when i am creating the Entity, it is not setting it

    Do I need to look in any other place?

  • User Avatar
    0
    hasan created

    Let me summarise the things i have done and let me know how to solve this

    1. In the Entity Framework AbpModule Class. I have added as below
    public class DineConnectDataModule : AbpModule
        {
            public override void PreInitialize()
            {
                //web.config (or app.config for non-web projects) file should containt a connection string named "Default".
                Configuration.DefaultNameOrConnectionString = "Default";
                Configuration.UnitOfWork.RegisterFilter("ConnectFilter", true);
            }
    
            public override void Initialize()
            {
                //AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) =>
                //    (context as DineConnectDbContext).AuditEntries.AddRange(audit.Entries);
                Configuration.Auditing.IsEnabled = true;
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
                Database.SetInitializer(new MigrateDatabaseToLatestVersion<DineConnectDbContext, Migrations.Configuration>());
            }
        }
    
    1. Here is the interface for Session Filter
    namespace DinePlan.DineConnect.Filter
    {
        public interface IOrganization
        {
            int Oid { get; set; }
        }
    }
    
    1. On DbContext as below
    public override void Initialize()
            {
                base.Initialize();
                this.SetFilterScopedParameterValue("ConnectFilter", "oid", ConnectSession.OrgId);
            }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Filter("ConnectFilter", (IOrganization entity, int oid) => entity.Oid == oid, 0);
           }
    
    1. Account Controller as below
    private async Task SignInAsync(User user, ClaimsIdentity identity = null, bool rememberMe = false)
            {
                if (identity == null)
                {
                    identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                }
    
                identity.AddClaim(new Claim("Organization", "1"));
                AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberMe }, identity);
            }
    
    1. SessionAppService as below
    public class SessionAppService : DineConnectAppServiceBase, ISessionAppService
        {
            private readonly ConnectSession _mySession;
    
            public SessionAppService(ConnectSession mySession)
            {
                _mySession = mySession;
            }
    }
    
    1. My Session as below
    public class ConnectSession : ITransientDependency
        {
            public int OrgId 
            {
                get
                {
                    var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
                    var tenantIdClaim = claimsPrincipal?.Claims.FirstOrDefault(c => c.Type == "Organization");
                    if (!string.IsNullOrEmpty(tenantIdClaim?.Value))
                    {
                        return Convert.ToInt32(tenantIdClaim.Value);
                    }
                    return 0;
                }
    
                set
                {
                    var currentPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
                    var identity = currentPrincipal.Identity as ClaimsIdentity;
                    if (identity == null)
                        return;
    
                    var existingClaim = identity.FindFirst("Organization");
                    if (existingClaim != null)
                        identity.RemoveClaim(existingClaim);
    
                    // add new claim
                    identity.AddClaim(new Claim("Organization", value.ToString()));
                }
               
            }
        }
    
    1. Here is the place where it is trying to insert and its screenshots

    Ref IMAGE 1

    Ref IMAGE 2

    1. See the INSERT STATEMENTS
    exec sp_executesql N'INSERT [dbo].[MenuItems]([Name], [BarCode], [AliasCode], [AliasName], [ItemDescription], [ForceQuantity], [ForceChangePrice], [CategoryId], [TenantId], [ProductType], [Tag], [RefLocation], [TransactionTypeId], [HsnCode], [Oid], [IsDeleted], [DeleterUserId], [DeletionTime], [LastModificationTime], [LastModifierUserId], [CreationTime], [CreatorUserId])
    VALUES (@0, NULL, @1, NULL, NULL, @2, @3, @4, @5, @6, NULL, @7, NULL, NULL, @8, @9, NULL, NULL, NULL, NULL, @10, @11)
    SELECT [Id]
    FROM [dbo].[MenuItems]
    WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()',N'@0 nvarchar(100),@1 nvarchar(50),@2 bit,@3 bit,@4 int,@5 int,@6 int,@7 int,@8 int,@9 bit,@10 datetime2(7),@11 bigint',@0=N'TTTT',@1=N'43234',@2=0,@3=0,@4=2,@5=1,@6=1,@7=0,@8=0,@9=0,@10='2017-08-23 09:43:33.3571316',@11=2
    go
    
    1. One Last Time. Here is the Select Statement which is working perfectly
    exec sp_executesql N'SELECT 
        [Extent1].[Id] AS [Id], 
        [Extent1].[BarCode] AS [BarCode], 
        [Extent1].[AliasCode] AS [AliasCode], 
        [Extent1].[AliasName] AS [AliasName], 
        [Extent1].[CategoryId] AS [CategoryId], 
        [Extent2].[Name] AS [Name], 
        [Extent1].[CreationTime] AS [CreationTime], 
        [Extent1].[CreatorUserId] AS [CreatorUserId], 
        [Extent1].[Name] AS [Name1], 
        [Extent1].[ForceChangePrice] AS [ForceChangePrice], 
        [Extent1].[ForceQuantity] AS [ForceQuantity], 
        [Extent1].[ItemDescription] AS [ItemDescription]
        FROM   (SELECT [Var_17].[Id] AS [Id], [Var_17].[Name] AS [Name], [Var_17].[BarCode] AS [BarCode], [Var_17].[AliasCode] AS [AliasCode], [Var_17].[AliasName] AS [AliasName], [Var_17].[ItemDescription] AS [ItemDescription], [Var_17].[ForceQuantity] AS [ForceQuantity], [Var_17].[ForceChangePrice] AS [ForceChangePrice], [Var_17].[CategoryId] AS [CategoryId], [Var_17].[CreationTime] AS [CreationTime], [Var_17].[CreatorUserId] AS [CreatorUserId]
            FROM [dbo].[MenuItems] AS [Var_17]
            WHERE (([Var_17].[Oid] = @DynamicFilterParam_7) OR (@DynamicFilterParam_8 IS NOT NULL)) AND (([Var_17].[TenantId] = @DynamicFilterParam_5) OR (@DynamicFilterParam_6 IS NOT NULL)) AND (([Var_17].[IsDeleted] = @DynamicFilterParam_1) OR (@DynamicFilterParam_2 IS NOT NULL)) ) AS [Extent1]
        LEFT OUTER JOIN  (SELECT [Var_18].[Id] AS [Id], [Var_18].[Name] AS [Name]
            FROM [dbo].[Categories] AS [Var_18]
            WHERE (([Var_18].[TenantId] = @DynamicFilterParam_5) OR (@DynamicFilterParam_6 IS NOT NULL)) AND (([Var_18].[IsDeleted] = @DynamicFilterParam_1) OR (@DynamicFilterParam_2 IS NOT NULL)) ) AS [Extent2] ON [Extent1].[CategoryId] = [Extent2].[Id]
        ORDER BY [Extent1].[Name] ASC
        OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY ',N'@DynamicFilterParam_7 int,@DynamicFilterParam_8 bit,@DynamicFilterParam_5 int,@DynamicFilterParam_6 bit,@DynamicFilterParam_1 bit,@DynamicFilterParam_2 bit',@DynamicFilterParam_7=1,@DynamicFilterParam_8=NULL,@DynamicFilterParam_5=1,@DynamicFilterParam_6=NULL,@DynamicFilterParam_1=0,@DynamicFilterParam_2=NULL
    go
    

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    DataFilters are only for filtering data. If you want to set field while saving an entity, you must override SaveChanges of your DbContext, set field if entity implements your interface and then, you can call base SaveChanges.

    Also, thank you very much for sharing your detailed work.

  • User Avatar
    0
    hasan created

    Dear Ismac,

    I have another Issue here. It would be great if you can give me a solution.

    I am able to set the Claim in my Session as below. It is perfectly setting the value (REF 1.png)

    When it is fetching for the first time, it is perfectly taking the correct value but it is doing for the second time.

    Please refer 2.png and 3.png

  • User Avatar
    0
    alirizaadiyahsi created

    Hi @Hasan,

    Could you share the code that you set the claims value?

  • User Avatar
    0
    hasan created
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Security.Principal;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Abp.Dependency;
    using DinePlan.DineConnect.Authorization.Users;
    using Microsoft.Owin.Security;
    
    namespace DinePlan.DineConnect.Session
    {
        public class ConnectSession : ITransientDependency
        {
            public ConnectSession()
            {
                var test = "";
            }
            public int OrgId 
            {
                get
                {
                    var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
                    var tenantIdClaim = claimsPrincipal?.Claims.FirstOrDefault(c => c.Type.Equals( "Organization"));
                    if (!string.IsNullOrEmpty(tenantIdClaim?.Value))
                    {
                        return Convert.ToInt32(tenantIdClaim.Value);
                    }
                    return 0;
                }
    
                set
                {
                    var currentPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
                    var identity = currentPrincipal.Identity as ClaimsIdentity;
                    if (identity == null)
                        return;
    
                    var existingClaim = identity.FindFirst("Organization");
                    if (existingClaim != null)
                        identity.RemoveClaim(existingClaim);
    
                    // add new claim
                    identity.AddClaim(new Claim("Organization", value.ToString()));
                }
               
            }
        }
    
      
    }
    
  • User Avatar
    0
    alirizaadiyahsi created

    I mean, where did you set ConnectSession.OrgId?

    I can see the code that is in your latest post at image, but I can't see, where did you set this property? In "SignInAsync"? There is a code block above that is setting this property.

    identity.AddClaim(new Claim("Organization", "1"));
    

    Is it the code that you use set this property?

  • User Avatar
    0
    hasan created

    Here we are setting the value

    private async Task SignInAsync(User user, ClaimsIdentity identity = null, bool rememberMe = false)
            {
                if (identity == null)
                {
                    identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                }
                if (user != null)
                {
                    var locationId = _userManager.GetDefaultLocationForUserAsync(user.Id);
                    if (locationId.HasValue)
                    {
                        var location = await _userManager.GetDefaultLocationInfoAsync(locationId);
                        if (location!=null && location.CompanyRefId>0)
                            identity.AddClaim(new Claim("Organization", location.CompanyRefId.ToString()));
                    }
                }
    
    
                AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberMe }, identity);
            }
    

    But everything the location changes, we are setting through a Service as well like one below

    public async Task AppendDefaultUserOrganization(UserToOrganizationUnitInput input)
            {
                var existList = _userDefaultOrganizationRepo.FirstOrDefault(a => a.UserId == input.UserId);
                if (existList==null)
                {
                    UserDefaultOrganization newDefaultUser = new UserDefaultOrganization();
                    newDefaultUser.UserId = input.UserId;
                    newDefaultUser.OrganizationUnitId = input.OrganizationUnitId;
    
                    await _userDefaultOrganizationRepo.InsertOrUpdateAndGetIdAsync(newDefaultUser);
                }
                else
                {
                    var item = await _userDefaultOrganizationRepo.GetAsync(existList.Id);
                    item.OrganizationUnitId = input.OrganizationUnitId;
                    await _userDefaultOrganizationRepo.InsertOrUpdateAndGetIdAsync(item);
                }
                if (input.OrganizationId > 0 && ConnectSession!=null)
                {
                    ConnectSession.OrgId = input.OrganizationId;
                }
            }
    
  • User Avatar
    0
    alirizaadiyahsi created

    Error is occuring while setting not getting.

    Put break point SignInAsync and AppendDefaultUserOrganization to understand what value are you setting for OrgId. There may be some logical problem your if-else conditions.

  • User Avatar
    0
    hasan created

    It’s properly setting the values on login in and I am changing every time user changes as well

    The setting and getting is properly happening for the first time

    On second time, it is fetching, it is taking the value which we got set during login

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Hasan,

    I think the problem is related to below lines

    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberMe }, identity);
    

    When you change the value of OrgId, these lines are called and it triggers SignInAsync again and your last set value is lost. Why did you need those lines ?

  • User Avatar
    0
    hasan created

    It was in the default code

    In VERSION 1.9 ANGULAR JS/ASP.NET MVC

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi Hasan,

    If you can send your project to us, we can check both session and datepicker problems.

  • User Avatar
    0
    hasan created

    Dear Ismac

    I have sent the files to your email Id and continuously sending a followup as well

    Let me know when I can expect the reply