如何将React.js中的JSON值传递至.NET抽象类参数?
解决方案
你遇到的问题本质是.NET在反序列化抽象类参数时,无法通过JSON自动识别对应的具体实现类,再加上代码存在字段缺失、属性引用错误的问题,按以下步骤修改即可:
1. 配置抽象类反序列化的类型鉴别规则
.NET反序列化抽象/父类对象时,需要额外的标识字段判断具体要实例化哪个子类,按你使用的序列化组件二选一配置:
如果你使用.NET默认的System.Text.Json序列化
给你的ConcreteRegistryInfo抽象类加上派生类类型标识配置:
using System.Text.Json.Serialization; [DataContract] [KnownType(typeof(ConcreteOtherRegistry))] [KnownType(typeof(ConcreteForeignerRetailRegistry))] [KnownType(typeof(ConcreteUndetailedRegistry))] [KnownType(typeof(ConcreteRetailRegistry))] [KnownType(typeof(ConcretePublicRegistry))] [KnownType(typeof(ConcreteCorporateRegistry))] // 给每个子类配置对应的鉴别标识,其余子类按需补充该配置即可 [JsonDerivedType(typeof(ConcreteRetailRegistry), typeDiscriminator: "RetailRegistry")] public abstract class ConcreteRegistryInfo { // 原有代码不变 }
如果你使用Newtonsoft.Json序列化
在Program.cs/Startup.cs里配置序列化时开启类型名称输出:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; });
2. 补全前端JSON的必填字段
你的ConcreteRegistryInfo抽象类标记了4个必填的DataMember,现有APPLICATION对象缺少Status、LastUpdated、OperationRefNo三个字段,必须补全,同时加上第一步的类型鉴别字段。
调整后的APPLICATION示例:
let APPLICATION = { // System.Text.Json对应上面配置的标识,Newtonsoft.Json则填"$type": "你的命名空间.ConcreteRetailRegistry, 你的程序集名称" "$type": "RetailRegistry", IdentityNumber:IdentityNumber, Name:Name, SurName:SurName, FatherName:FatherName, MotherName:MotherName, PlaceOfBirth:PlaceOfBirth, Gender:Gender, Email:Email, DateOfBirth:DateOfBirth, DayOfBirth:DayOfBirth, MonthOfBirth:MonthOfBirth, YearOfBirth:YearOfBirth, GsmNumber:GsmNumber, PhoneNumber:PhoneNumber, Retired:Retired, Address:Address, Oid:Oid, // 补全抽象类必填字段,值按实际业务逻辑赋值即可 Status: 1, LastUpdated: new Date().getTime(), OperationRefNo: 10001 }
3. 修复后端接口代码错误
你定义的SaveApplicationParameters类只有registryInfo属性,但接口中直接读取不存在的application属性,必然为空。修改接口逻辑,用传入的registryInfo构造你需要的ConcreteApplication对象:
[HttpPost] public object[] SaveApplication([FromBody] SaveApplicationParameters saveApplicationParameters) { // 把传入的registryInfo强转为对应实现类 var retailRegistry = saveApplicationParameters.registryInfo as ConcreteRetailRegistry; // 构造ConcreteApplication对象,属性按你的业务逻辑赋值 ConcreteApplication application = new ConcreteApplication { RegistryInfo = retailRegistry, // 其余属性按需赋值 }; try { Com.BS.WaterSupplyAndSeverage.Services.WaterSupplyAndSewerage wssService = new Com.BS.WaterSupplyAndSeverage.Services.WaterSupplyAndSewerage(); wssService.SaveApplication(application); object[] result = new object[1]; result[0] = application.ApplicationNo; return result; } catch (Exception e) { FileLogger.Error(CLASS_NAME, "SaveApplication", e.Message, e.StackTrace, application, policy); BSCommunicationException commException = PrepareCommunicationException(e); throw new FaultException<BSCommunicationException>(commException, new FaultReason(commException.ExceptionMessage)); } }
4. 前端请求可选优化
给axios请求显式指定JSON请求头,避免部分环境下序列化异常:
const body = { registryInfo: APPLICATION }; axios.post('https://localhost:44396/api/SaveApplication', body, { headers: { 'Content-Type': 'application/json' } }) .then(async response => { SuccessOperation({ RESPONS_DATA: await response.data }); }) .catch(() => { FailedOperation({ RESPONSE_DATA: null }) });
内容的提问来源于stack exchange,提问作者Veysel Turan
相关产品推荐
相关产品推荐

