有条件地从要使用的数据中排除/包括属性.NET 5 Web API(字段级访问)



我正在开发一个。NET 5 Web Api,具有默认的System.Text.Json模型绑定。对于几个dto,我需要这样的东西:

public class MyDto
{
public string Name { get; set; }
public string PublicDetails { get; set; }
[IncludeForRoles("admin", "staff")]
public string InternalDetails { get; set; }
}

如果用户具有除";管理员";或";工作人员";调用返回上述dto的端点;内部细节";应在模型绑定时忽略,而不应添加到序列化的dto中。有标准的方法吗?如果没有,我如何手动实现此行为?

有一个[JsonIgnore]属性,它接受一个条件,如果属性为null或默认值,该条件将忽略属性。

假设您知道控制器中的角色,则仅在具有相关角色的情况下获取InternalDetails信息,如果没有,则将其保持为null。这也减少了查询时间,因为您没有得到不需要的信息。

我建议使用Newtonsoft。用于序列化的JSON库,并实现自定义ContractResolver以动态决定要序列化的字段。

我找到了一种满足要求但有以下缺点的变通方法:

  • 从数据库加载不需要的数据(不能使用Automapper的.ProjectTo(
  • 映射后修改数据(无法将服务注入Automapper的Profile,请参阅此处(
  • 每个属性都必须添加两个属性,在某些情况下应该忽略这两个属性

你看,这不是一个美丽而优雅的解决方案。请随意推荐一个更好的!

属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IncludeForRolesAttribute : Attribute
{
public IncludeForRolesAttribute(params string[] roleNames)
{
RoleNames = roleNames;
}
public string[] RoleNames { get; }
}

Automapper映射操作:

public class RoleBasedSetNullAction<TSource, TDestination> : IMappingAction<TSource, TDestination>
{
private readonly ITokenAccessor _tokenAccessor;
public RoleBasedSetNullAction(ITokenAccessor tokenAccessor)
{
_tokenAccessor = tokenAccessor ?? throw new ArgumentNullException(nameof(tokenAccessor));
}
public void Process(TSource source, TDestination destination, ResolutionContext context)
{
IEnumerable<PropertyInfo> props = typeof(TDestination).GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(IncludeForRolesAttribute)));
foreach (PropertyInfo prop in props)
{
IncludeForRolesAttribute attr = prop.GetCustomAttribute<IncludeForRolesAttribute>();
if (!_tokenAccessor.UserRoles.Intersect(attr.RoleNames).Any())
{
prop.SetValue(destination, null);
}
}
}
}

DTO:

public class MyDto : BaseEntityDto
{
public string Name { get; set; }

public string PublicDetails { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[IncludeForRoles("admin", "staff")]
public string InternalDetails { get; set; }
}

Automapper映射配置文件:

public class MyDtoMappingProfile : Profile
{
public MyDtoMappingProfile()
{
CreateMap<MyEntity, MyDto>()
.AfterMap<RoleBasedSetNullAction<MyEntity, MyDto>>();
}
}

相关内容

  • 没有找到相关文章

最新更新