Hi, I have already included the code in my last post. By here it is again:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "CreatorUserId")
{
property.ShouldSerialize =
instance =>
{
JobLocationDto e = (JobLocationDto)instance;
if (e.CreatorUserId.Value != GetCurrentUser().Id)
{
return false;
}
return true;
};
}
return property;
}
}
Please note that I have not injected the UserManager to the ShouldSerializeContractResolver class yet to use the GetCurrentUser, but the whole idea is dropping the Audited fields from the the response if the caller is not Admin or the owner of the entity
public async Task<ListResultDto<JobLocationDto>> GetJobLocationList(GetJobLocationListInput input)
{
if (AbpSession.UserId != null)
{
if (await UserManager.IsGrantedAsync(GetCurrentUser().Id, AppPermissions.Pages_Administration_Jobs_Locations))
{
var jobLocationsManage = await _jobLocationRepository.GetAll().Where(jobLocation => input.State == Common.VisibilityState.All ? (jobLocation.IsActive || !jobLocation.IsActive) :
input.State == Common.VisibilityState.Active ? jobLocation.IsActive : !jobLocation.IsActive).ToListAsync();
return new ListResultDto<JobLocationDto>(ObjectMapper.Map<List<JobLocationDto>>(jobLocationsManage));
}
}
var jobLocations = await _jobLocationRepository.GetAll().Where(jobLocation => jobLocation.IsActive).ToListAsync();
foreach (var jobLocation in jobLocations)
{
//this jb would be one jobLocation in string format, and the method returns Task<ListResultDto<JobLocationDto>>!!!!
var jb = JsonConvert.SerializeObject(ObjectMapper.Map<JobLocationDto>(jobLocation), new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver() });
}
return new ListResultDto<JobLocationDto>(ObjectMapper.Map<List<JobLocationDto>>(jobLocations));
}
I have also tried to conditionally ignore the property in the CustomeDtoMapper class like below:
configuration.CreateMap<JobLocation, JobLocationDto>()
.ForMember(jl => jl.CreationTime, option => option.Condition(jl => jl.CreatorUserId == ADMIN_USER_ID));
but there are 2 problems with this approach:
Today is my licence expires and I assume I no longer can post any comment on this thread. So I really appreciate a response ASAP, so I could reply back if is needed. I wish I could afford to renew my licence :cry:
Thank you very much guys ;)
Any comment on this? :roll:
I managed to hit the breakpoint and its is ignoring the property that I want. The problem however is that it returns a JSON in string format but I need to have my API return the DTO class so I could easily use it in the Angular project!
Any thought?
Hey Aaron,
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType == typeof(JobLocationDto) && property.PropertyName == "CreatorUserId")
{
property.ShouldSerialize =
instance =>
{
JobLocationDto e = (JobLocationDto)instance;
if (true) {
return true;
}
else
{
return false;
}
};
}
return property;
}
}
and this is the AppService API method:
public async Task<ListResultDto<JobLocationDto>> GetJobLocationList(GetJobLocationListInput input)
{
var jobLocations = await _jobLocationRepository.GetAll().Where(jobLocation => jobLocation.IsActive).ToListAsync();
return new ListResultDto<JobLocationDto>(ObjectMapper.Map<List<JobLocationDto>>(jobLocations));
}
As you can see I am not using the JsonConvert.SerializeObject to serialize it as the method is supposed to return Task<ListResultDto<JobLocationDto>> not a JSON result. I am pretty sure I am missing something in my code! but what?!
Hi Champs! Well at first I was looking for the second one but now that you have raised it, both! With the second one however, I have found it a bit hard to implement it with the current project structure. I assume that I need to define the ShouldSerializeManager by where the Dto classes are (Application.Shared). But the Application.Shared does not have a reference to the UserManager so I could check the caller's permission and roles to decide whether or not serialize the property. I have also tried the second approach by defining the ShouldSerializeContractResolver in the Application project by one of the AppServices implementation but it does work! In the below code I was expecting that the GetJobLocationList() in the JobLocationAppService not returning the CreatoUserId for the callers who have nnot been granted the required permission but it does!
public class JobLocationAppService : AgbizCareersDemoAppServiceBase, IJobLocationAppService
{
public async Task<ListResultDto<JobLocationDto>> GetJobLocationList(GetJobLocationListInput input)
{
var jobLocations = await _jobLocationRepository.GetAll().Where(jobLocation => jobLocation.IsActive).ToListAsync();
return new ListResultDto<JobLocationDto>(ObjectMapper.Map<List<JobLocationDto>>(jobLocations));
}
}
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
UserManager userManager = new UserManager();
if (property.DeclaringType == typeof(JobLocationDto) && property.PropertyName == "CreatorUserId")
{
property.ShouldSerialize =
instance =>
{
JobLocationDto e = (JobLocationDto)instance;
if (userManager.UserManager.IsGrantedAsync(userManager.UserManager.AbpSession.UserId.Value, AppPermissions.Pages_Administration_Jobs_Locations).Result) {
return true;
}
else
{
return false;
}
};
}
return property;
}
protected class UserManager : AgbizCareersDemoAppServiceBase { }
}
Thanks for your input in advance :)
Simply, can we apply the authorized and permission attributes at the property level like calss or methods? Basicallt, I want to filter some peoperties based on the caller permissions. Thanks :ugeek:
Well done! Thanks for that Aaron, but would you please tell me why I could do it without that inheritance? And why the UserLinkManager does not inherit the ITransientDependency? Does the documentation have any reference to the ITransientDependency?
Cheers,
I have got the following classes/interface:
public interface IJobManager
{
Task<Job> Publish(Job job);
}
public class JobManager: IJobManager
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly ILocalizationManager _localizationManager;
private readonly IRepository<Job, long> _jobRepository;
public JobManager(
IUnitOfWorkManager unitOfWorkManager,
ILocalizationManager localizationManager,
IRepository<Job, long> jobRepository
)
{
_unitOfWorkManager = unitOfWorkManager;
_localizationManager = localizationManager;
_jobRepository = jobRepository;
}
public async Task<Job> Publish(Job job) {
//ToDo: Check the available credit
job.PublishStart = DateTime.Now;
return job;
}
}
public class JobAppService : AgbizCareersDemoAppServiceBase, IJobAppService
{
private readonly IRepository<Job, long> _jobRepository;
private readonly IJobManager _jobManager;
public JobAppService(
IRepository<Job, long> jobRepository,
IJobManager jobManager)
{
_jobRepository = jobRepository;
_jobManager = jobManager;
}
[AbpAuthorize(AppPermissions.Pages_Job_Manage)]
public async Task<JobDto> PublishJob(EntityDto<long> input)
{
var job = await _jobRepository.GetOwnAsync(input.Id);
job = await _jobManager.Publish(job);
return ObjectMapper.Map<JobDto>(job);
}
}
I am getting the following error in the log file:
'AgbizCareersDemo.Jobs.JobAppService' is waiting for the following dependencies:
- Service 'AgbizCareersDemo.Jobs.IJobManager' which was not registered.
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'AgbizCareersDemo.Jobs.JobAppService' as it has dependencies to be satisfied.
I have already created a service class in my other projects and I didn't have to resolve any dependency myself. Has anything been changed in that regard in the recent update?
Hey fellas, can somebody please guide me on how to debug an AppService with AbpAuthorize attribute via swagger? I know that I should pass something in the header to fulfill the authorization requirements but not sure what! Is there any particular setting in the application itself or swagger that I could set to dismiss the authorization attribute temporarily for testing methods functionalities purposes?
Cheers,
Hi Aaron, Thanks for your comment. Well, the problem is I can't distinguish the business logic and the requested application functionalities. For instance in the UserAppService>CreateUserAsync, almost all the business logic of creating a user is located in the method body itself rather than the UserManager in the Domain layer.
thanks