使用 .NET 5 Web API(字段级访问)从 dto 有条件地排除/包含属性 [英] Conditionally exclude/include properties from dto using .NET 5 Web API (Field Level Access)

查看:19
本文介绍了使用 .NET 5 Web API(字段级访问)从 dto 有条件地排除/包含属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm developing a .NET 5 Web Api with the default System.Text.Json model binding. For several dtos I need something like this:

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

如果用户的角色不是admin"或员工"调用返回上述 dto 的端点,属性InternalDetails";应该在模型绑定上被忽略,而不是被添加到序列化的 dto 中.有没有标准的方法来做到这一点?如果没有,我如何手动实现此行为?

If a user with a role other than "admin" or "staff" calls the endpoint which returns the above mentioned dto, the property "InternalDetails" should be ignored on model binding and not be added to the serialized dto. Is there a standard way to do this? If not, how could I implement this behavior manually?

推荐答案

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

I've found a kind of workaround which meets the requirements but has the following disadvantages:

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

你看,这不是一个漂亮优雅的解决方案.随意推荐一个更好的!

You see, this is not a beautiful and elegant solution. Feel free to suggest a better one!

属性:

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

Automapper 映射操作:

The Automapper Mapping Action:

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 映射配置文件:

The Automapper Mapping Profile:

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

这篇关于使用 .NET 5 Web API(字段级访问)从 dto 有条件地排除/包含属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆