ASP.NET MVC开发RESTful API时如何将数据库卡片数据拆分为display和action对象
解决方案核心思路
数据库存储的是拍平的卡片字段,不需要修改表结构,只需要在API层定义对应目标JSON结构的强类型DTO,把EF查询出来的拍平卡片实体手动映射为嵌套的DTO结构即可,不要直接将EF实体序列化返回。
第一步:定义对应JSON层级的DTO类
按照目标JSON的嵌套关系,分层定义DTO,所有字段补默认空值,避免序列化出null值:
// 对应config节点 public class ConfigDto { public string Type { get; set; } public string Name { get; set; } public string Template { get; set; } } // 对应卡片下的display嵌套对象,兼容两类卡片的所有展示字段 public class CardDisplayDto { public string PrimaryMessage { get; set; } = string.Empty; public string PrimaryButton { get; set; } = string.Empty; public string DismissButton { get; set; } = string.Empty; public string Priority { get; set; } = string.Empty; public string CardId { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; } // 对应卡片下的action嵌套对象 public class CardActionDto { public string PageId { get; set; } = string.Empty; public string CustomLink { get; set; } = string.Empty; // 强制初始化空数组,避免序列化出null public List<object> Params { get; set; } = new List<object>(); } // 对应cardContent数组的单条卡片结构 public class CardContentItemDto { public CardDisplayDto Display { get; set; } public CardActionDto Action { get; set; } } // 对应整个响应的根结构 public class ApiResponseDto { public ConfigDto Config { get; set; } public List<CardContentItemDto> CardContent { get; set; } }
第二步:修改接口逻辑,手动映射字段为嵌套结构
不要直接返回context.cards.ToList(),通过LINQ投影把拍平的实体字段拆分到Display和Action子对象中:
public IHttpActionResult Post(string appCountry = null, string appLanguage = null) { DealsEntities context = new DealsEntities(); // 构造config对象,确保template值正确赋值 var config = new ConfigDto { Type = "custom", Name = "Deals and Offers", Template = "customTextImageActionCard1" }; // 映射数据库拍平的卡片实体为嵌套结构 var cardContent = context.cards // 若有自定义转换逻辑,提前把查询结果加载到内存,避免EF翻译SQL报错 .AsEnumerable() .Select(card => new CardContentItemDto { // 展示类字段全部映射到Display子对象 Display = new CardDisplayDto { PrimaryMessage = card.primaryMessage ?? string.Empty, PrimaryButton = card.primaryButton ?? string.Empty, DismissButton = card.dismissButton ?? string.Empty, Priority = card.priority ?? string.Empty, CardId = card.cardId ?? string.Empty, Title = card.title ?? string.Empty }, // 跳转动作类字段全部映射到Action子对象 Action = new CardActionDto { PageId = card.pageId ?? string.Empty, CustomLink = card.customLink ?? string.Empty, Params = card.params ?? new List<object>() } }) .ToList(); // 组装最终响应返回 return Ok(new ApiResponseDto { Config = config, CardContent = cardContent }); }
关键注意事项
- ASP.NET MVC默认的JSON序列化器会自动将C#的PascalCase属性名转换为camelCase,和目标JSON的字段命名完全匹配,不需要额外调整。
- 之前出现
template值为空、params为null的问题,用强类型DTO后会从根源避免,因为所有字段的赋值逻辑是显式的,不会出现命名冲突。 - 不需要修改数据库表结构,所有拆分逻辑都在API输出层完成,不影响现有数据存储。
内容的提问来源于stack exchange,提问作者Hansen Phelix
相关产品推荐
相关产品推荐

