.NET Core中复用模型:避免Web应用暴露移动端专属属性
移动端与Web端请求模型复用方案(避免重复代码+隐藏专属属性)
问题描述
我正在开发一款应用,需要为移动端和Web端实现不同的请求模型:移动端会传递一些额外属性,但这些属性不能暴露给Web端。目前已有可运行的代码,但不想重复编写移动端专属属性的代码,该如何优化?
现有代码问题
当前代码中,移动端请求类MobileAppConsumptionDetailsRequest需要重复实现IMobileAppBaseRequestDto接口的所有属性,导致代码冗余。
优化方案
方案1:基于基类继承实现复用(推荐)
通过将移动端专属属性抽成抽象基类,并让移动端请求类继承Web端的业务请求类,彻底消除代码重复,同时实现模型隔离。
修改后的代码
// Web端请求模型:仅包含业务必要属性,无移动端专属字段 public class ConsumptionDetailsRequestDto { public string AccountResourceId { get; set; } = null!; } // 移动端公共属性基类:继承Web端请求模型,封装所有移动端专属属性 public abstract class MobileAppBaseRequestDto : ConsumptionDetailsRequestDto { public string? RequestingOrganisationTransactionReference { get; set; } public string? UserCaseName { get; set; } public bool IsMerchant { get; set; } public bool PushUpdateStatus { get; set; } public string? IpInfo { get; set; } public string? Channel { get; set; } public string? AppVersion { get; set; } public string? LanguageCode { get; set; } public string? DeviceId { get; set; } public string? DeviceMaker { get; set; } public string? DeviceType { get; set; } public string? OS { get; set; } public string? PushId { get; set; } public string? Latitude { get; set; } public string? Longitude { get; set; } public string? Msisdn { get; set; } } // 移动端具体请求类:无需重复编写属性,直接继承基类即可 public class MobileAppConsumptionDetailsRequest : MobileAppBaseRequestDto { // 自动拥有Web端业务属性 + 移动端专属属性 }
如何保证属性不暴露给Web端
- API层面隔离:Web端接口的参数类型使用
ConsumptionDetailsRequestDto,即使前端传入移动端专属属性,模型绑定会自动忽略这些字段,不会被业务逻辑处理,也不会出现在接口文档(如Swagger)中。 - 序列化配置:如果使用JSON序列化,可开启「忽略未知属性」的配置,避免反序列化错误:
- System.Text.Json:设置
JsonSerializerOptions.IgnoreUnknownProperties = true - Newtonsoft.Json:设置
JsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore
- System.Text.Json:设置
方案2:使用接口默认实现(C# 8.0+)
如果需要保留接口的多实现能力,可利用C# 8.0的接口默认实现特性,让实现类无需重复编写属性:
public interface IMobileAppBaseRequestDto { // 为接口属性添加默认实现,无需实现类重复定义 public string? RequestingOrganisationTransactionReference { get; set; } public string? UserCaseName { get; set; } public bool IsMerchant { get; set; } public bool PushUpdateStatus { get; set; } public string? IpInfo { get; set; } public string? Channel { get; set; } public string? AppVersion { get; set; } public string? LanguageCode { get; set; } public string? DeviceId { get; set; } public string? DeviceMaker { get; set; } public string? DeviceType { get; set; } public string? OS { get; set; } public string? PushId { get; set; } public string? Latitude { get; set; } public string? Longitude { get; set; } public string? Msisdn { get; set; } } // Web端请求模型 public class ConsumptionDetailsRequestDto { public string AccountResourceId { get; set; } = null!; } // 移动端请求类:仅需继承业务类并实现接口,无需重复写属性 public class MobileAppConsumptionDetailsRequest : ConsumptionDetailsRequestDto, IMobileAppBaseRequestDto { // 空实现即可,接口默认提供属性的getter/setter }
方案对比
- 基类继承方案:结构清晰,OOP逻辑明确,反射、模型绑定和接口文档生成更友好,适合大多数场景。
- 接口默认实现方案:支持多接口实现,但属性是接口的隐式成员,在某些反射场景下需要特殊处理,适合复杂多继承场景。
内容的提问来源于stack exchange,提问作者Kamran Khan
相关产品推荐
相关产品推荐

