如何在Web API JSON响应中删除相关EF实体的属性

本文关键字:EF 实体 属性 删除 Web API 响应 JSON | 更新日期: 2023-09-27 18:27:44

我正在开发基于Web API 2的服务,使用Entity Framework 6进行持久性,使用ASP.NET Identity进行身份验证。我使用实体框架的默认IdentityUser实现。

假设我有一个这样的实体:

public class Example
{
    [Key]
    public string Id { get; set; }
    public string Foo { get; set; }
    public string Bar { get; set; }
    public virtual IdentityUser OwningUser { get; set; }
}

在我的Web API控制器中,一个HTTPGET请求以这种方式返回一个记录:

public async Task<Example> Get( string id )
{
    var example = await _exampleRepository.FindByIdAsync( id );
    return example;
}

这很好用。然而,一个请求会返回如下JSON:

{
    id: "some id",
    foo: "some foo",
    bar: "some bar",
    owningUser: {
        claims: [],
        logins: [],
        roles: [
            {
                userId: "some user id",
                roleId: "some role id"
            }
        ],
        securityStamp: "jadshgiuahsduigh",
        passwordHash: "adsghasdjgiasdg",
        email: "some@email.com",
        emailConfirmed: false,
        ... snip ...
        userName: "some user",
        id: "some user id"
    }
}

我不想返回所有的用户数据!我想做的是以某种方式截取正在生成的JSON和要包含的白名单属性,这样在这种情况下,从API返回的序列化IdentityUser对象将只包含以下内容:

owningUser: {
    userName: "some user",
    id: "some user id"
}

我怎样才能做到这一点?我不想全面截断IdentityUser记录;这必须是我可以在控制器操作的基础上选择的。这是可以通过动作过滤器实现的吗?拦截需要在管道的什么地方进行?理想情况下,我希望只对从控制器操作返回的对象图中的IdentityUser实例进行自定义序列化,而不是直接操纵完成的JSON响应。如果相关的话,我将运行Web API作为OWIN中间件。

如何在Web API JSON响应中删除相关EF实体的属性

一个好的解决方案是使用Dtos,AutoMapper/Projection,这样你就可以设置你的dto以包括你想要返回的内容,通过使用AutoMapper和投影,你可以将你的原始实体映射到Dtos上,反之亦然。

使用自动映射程序:所以你定义一个UserD如下:

public class UserDto
    {
        public int Id { get; set; }
        public string UserName { get; set; }
    }

然后在你的应用程序启动时,你定义IdentityUser和UserD之间的映射如下:

Mapper.CreateMap<IdentityUser, UserDto>();

然后,当你有了示例实体时,你可以像这个一样将IdentityUser映射到UserDto

var dto = Mapper.Map<UserDto>(example.OwningUser);

而你只返回dto。

使用投影您可以使用Select-Linq方法只选择要从数据库返回的字段,因此如下所示:

var userDto = dbExamplesSet
                .Select(e => e.OwningUser)
                .Select(u => new UserDto
                {
                    Id = u.Id, 
                    UserName = u.UserName
                }).SingleOrDefault(u=> u.Id == someUserId);

希望能有所帮助。