In ASP.NET Boilerplate, there are built-in Data Filters like Tenant filter, and we could use SetTenantId
to enable querying specific tenantId
.
As per the official document, it did not support custom Filter
in EF Core, unlike EF 6.x.
I am wondering how to achieve a similar filter for OrganizationUnitId
parameter.
This is what I have done so far:
Override CreateFilterExpression
:
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
Expression<Func<TEntity, bool>> expression = null;
if (typeof(IMayHaveOrganizationUnit).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> mayHaveOUFilter = e => ((IMayHaveOrganizationUnit)e).OrganizationUnitId == CurrentOrganizationUnitId || (((IMayHaveOrganizationUnit)e).OrganizationUnitId == CurrentOrganizationUnitId) == IsMayHaveOrganizationUnitFilterEnabled;
expression = expression == null ? mayHaveOUFilter : CombineExpressions(expression, mayHaveOUFilter);
}
expression = expression == null ? base.CreateFilterExpression<TEntity>() : CombineExpressions(expression, base.CreateFilterExpression<TEntity>());
return expression;
}
I register the new filter by code below:
Configuration.UnitOfWork.RegisterFilter("MayHaveOrganizationUnit", true);
But, how can I implement the code to set OrganizationUnitId
?
SetTenantId
is used to configure the tenantId
, how could I configure OrganizationUnitId
from UnitOfWork
?
I try to inherit ClaimsAbpSession
like below:
public class CustomAbpSession : ClaimsAbpSession, ICustomAbpSession
{
private readonly IRepository<User, long> _userRepository;
public CustomAbpSession(
IRepository<User, long> userRepository,
IPrincipalAccessor principalAccessor,
IMultiTenancyConfig multiTenancy,
ITenantResolver tenantResolver,
IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider)
: base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
{
_userRepository = userRepository;
}
public virtual long? OrganizationUnitId
{
get
{
if (UserId != null)
{
var user = _userRepository.Get(UserId.Value);
return 1;
}
return null;
}
}
public long? ImpersonatorOrganizationUnitId => throw new NotImplementedException();
}
protected virtual long? GetCurrentOrganizationUnitIdOrNull()
{
return 3; // ((ICustomAbpSession)AbpSession).OrganizationUnitId;
}
Use code below to register custom IAbpSession
:
Configuration.ReplaceService(typeof(IAbpSession), () =>
{
IocManager.Register<IAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient);
});
Usage:
public List<Product> GetAll()
{
using (CurrentUnitOfWork.SetFilterParameter("MayHaveOrganizationUnit", "OrganizationUnitId", 2))
{
return _productRepositry.GetAll().ToList();
}
}
But, it always return value from OrganizationUnitId
in CustomAbpSession
, this method CurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
This isn't just a few lines of code.
Start with how IMayHaveTenant
is filtered in CreateFilterExpression
.
You can override ShouldFilterEntity
and CreateFilterExpression
in your DbContext
.
SetTenantId
is used to configure the tenantId, how could I configureOrganizationUnitId
fromUnitOfWork
?
You can use the equivalent SetFilterParameter
method.
But, it always return value from
OrganizationUnitId
inCustomAbpSession
, this methodCurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
From CurrentUnitOfWorkProvider.Current
, you can access Filters
:
protected virtual long? GetCurrentOrganizationUnitIdOrNull()
{
if (CurrentUnitOfWorkProvider != null &&
CurrentUnitOfWorkProvider.Current != null)
{
return CurrentUnitOfWorkProvider.Current
.Filters.FirstOrDefault(f => f.FilterName == "MayHaveOrganizationUnit")?
.FilterParameters["OrganizationUnitId"] as long?;
}
return ((ICustomAbpSession)AbpSession).OrganizationUnitId;
}