我正在开发基于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中间件。
一个好的解决方案是使用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);
希望能有所帮助。