I had posted this question on Stackoverflow few months ago.. The accepted answer on that question was working for me and my app in ANZ Version 6.3.1. Yesterday I updated my entire ANZ solution to V6.6.1. That code is not working now.
On the documentation for data filters it shows the code example below.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Filter("PersonFilter", (IHasPerson entity, int personId) => entity.PersonId == personId, 0);
}
Do I need to use the code shown in the documentation? And does it apply to EF Core?
15 Answer(s)
-
0
https://aspnetboilerplate.com/Pages/Documents/Articles\How-To\add-custom-data-filter-ef-core You can refer to this article to see if it can't be solved, please share some code that can reproduce the problem.
-
0
DB Context code:
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) { if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity))) { return true; } return false; } protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() { Expression<Func<TEntity, bool>> expression = null; if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> companyFilter = e => ((IHasCompany)e).CompanyId == CurrentCompanyId || (((IHasCompany)e).CompanyId == CurrentCompanyId) == IsCompanyFilterEnabled; expression = expression == null ? companyFilter : CombineExpressions(expression, companyFilter); } return base.CreateFilterExpression<TEntity>(); }
App service method, where filter is enabled.
public async Task<PagedResultDto<GetHomeForView>> GetAll(GetAllHomesInput input) { using (CurrentUnitOfWork.EnableFilter(AppConsts.CompanyFilter)) { using (CurrentUnitOfWork.SetFilterParameter(AppConsts.CompanyFilter, AppConsts.CompanyFilterParameter_CompanyId, GetCurrentUserCompany())) { //code removed } } }
When I run my code in debug (see image below), I can see the filter being applied in the using statement and there is a value as well. Yet once it goes inside the method code block and query executes, its not filtering the data. All rows in the table are being returned. All this code works perfectly in V6.3.1 solution.
-
0
I am using ASP.NET CORE MVC & jQuery .NET Core 2.2 v6.6.1 to test the filter and everything works fine.
Can you reproduce your problem using the 6.6.1 Demo project? If you can, please send the Demo project to: [email protected]
-
0
It's going to take some time and effort for me to recreate in the demo project. I dont have time to do that right now.
Today, I went back to my V631 solution and retested my data filters there and it seems to be broken there too. Its working on one app service and MVC view but not on another. I dont know how this broke, I had tested all of my pages and services after I applied the changes. Now I'm more confused as to what the issue could be!
- Can you confirm that my DB context code and my app service code shown in previous post is valid?
- Can you confirm if the changes to the UserClaimsPrincipalFactory class required to make the filtering work?
- Today I even added the changes to UserClaimsPrincipalFactory but its still not working!
-
0
I did some more testing/debugging.
I applied the code to the UserClaimsPrincipalFactory with two claims.
public override async Task<ClaimsPrincipal> CreateAsync(User user) { var claim = await base.CreateAsync(user); claim.Identities.First().AddClaim(new Claim("CompanyFilter", user.CompanyId.HasValue ? user.CompanyId.Value.ToString() : "")); claim.Identities.First().AddClaim(new Claim("NurseHomeFilter", user.NurseHomeId.HasValue ? user.NurseHomeId.Value.ToString() : "")); return claim; }
In my DB Context, I have added these two methods. In debug, I dont see these methods execute.
protected virtual int? GetCurrentUsersCompanyIdOrNull() { var userOuClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "CompanyFilter"); if (string.IsNullOrEmpty(userOuClaim?.Value)) { return null; } return Convert.ToInt32(userOuClaim.Value); } protected virtual int? GetCurrentUsersNurseHomeIdOrNull() { var userOuClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "NurseHomeFilter"); if (string.IsNullOrEmpty(userOuClaim?.Value)) { return null; } return Convert.ToInt32(userOuClaim.Value); }
In debug, i then checked the values of the filters when the "GetAll" repository method is called. They both have nothing?
> ? CurrentUnitOfWork.Filters Count = 5 [0]: {Abp.Domain.Uow.DataFilterConfiguration} [1]: {Abp.Domain.Uow.DataFilterConfiguration} [2]: {Abp.Domain.Uow.DataFilterConfiguration} [3]: {Abp.Domain.Uow.DataFilterConfiguration} [4]: {Abp.Domain.Uow.DataFilterConfiguration} > ? CurrentUnitOfWork.Filters[3] {Abp.Domain.Uow.DataFilterConfiguration} FilterName: "CompanyFilter" FilterParameters: Count = 0 IsEnabled: true > ? CurrentUnitOfWork.Filters[4] {Abp.Domain.Uow.DataFilterConfiguration} FilterName: "NurseHomeFilter" FilterParameters: Count = 0 IsEnabled: true
-
0
Can you confirm if the changes to the UserClaimsPrincipalFactory class required to make the filtering work?
What gave you that impression?
-
0
@aaron - The example document cited by @maliming in his first reply shows that code. I was NOT using that in version 6.3.1. That's what gave me that impression. Plus at this point I am just looking for help/direction to solve my issue. Is that too much to ask?
-
0
That shows how to store a value in claims. The value is used in
GetCurrentUsersOuIdOrNull
.It is not required for data filters to work if you get the value from elsewhere (e.g. DB).
-
0
I have just updated my solution V6.8 now and this data filtering is still not working for me.
Here on the Index view app service method, at the very first using statement, you can see the immediate window shows that both filters are enabled.
Here are the methods, which are in my base app service class, that get the current user company and home values. In this test, you can see both values are populated.
Yet when the code in the method executes, the query still returns all rows in the result?
-
0
You are discarding the filter
expression
, do these:protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() { // Expression<Func<TEntity, bool>> expression = null; var expression = base.CreateFilterExpression<TEntity>(); // Change to this if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> companyFilter = e => ((IHasCompany)e).CompanyId == CurrentCompanyId || (((IHasCompany)e).CompanyId == CurrentCompanyId) == IsCompanyFilterEnabled; expression = expression == null ? companyFilter : CombineExpressions(expression, companyFilter); } // return base.CreateFilterExpression<TEntity>(); return expression; // Change to this }
-
0
@aaron - Thanks! I noticed those differences just after I posted my last message. I applied those changes, but the filtering is still not working.
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) { if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity))) { return true; } if (typeof(IHasNurseHome).IsAssignableFrom(typeof(TEntity))) { return true; } return base.ShouldFilterEntity<TEntity>(entityType); } protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() { var expression = base.CreateFilterExpression<TEntity>(); if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> companyFilter = e => ((IHasCompany)e).CompanyId == CurrentCompanyId || (((IHasCompany)e).CompanyId == CurrentCompanyId) == IsCompanyFilterEnabled; expression = expression == null ? companyFilter : CombineExpressions(expression, companyFilter); } if (typeof(IHasNurseHome).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> nurseHomeFilter = e => ((IHasNurseHome)e).NurseHomeId == CurrentNurseHomeId || (((IHasNurseHome)e).NurseHomeId == CurrentNurseHomeId) == IsCompanyFilterEnabled; expression = expression == null ? nurseHomeFilter : CombineExpressions(expression, nurseHomeFilter); } return expression; }
Here in debug you can see that both filter are enabled and have values.
-
0
Show code for
CurrentCompanyId
. -
0
Here you go.
protected int? CurrentCompanyId = null; protected int? CurrentNurseHomeId = null; protected bool IsCompanyFilterEnabled => CurrentCompanyId != null && CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled("CompanyFilter") == true; protected bool IsNurseHomeFilterEnabled => CurrentNurseHomeId != null && CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled("NurseHomeFilter") == true;
-
1
CurrentCompanyId
andCurrentNurseHomeId
should be getter properties instead ofnull
fields.protected int? CurrentCompanyId => GetCurrentCompanyIdOrNull(); protected int? CurrentNurseHomeId => GetCurrentNurseHomeIdOrNull();
See AbpDbContext.cs#L77.