带[Serializable]的C#类接收Axios POST时字段为空的问题
为什么[Serializable]会导致接收对象为空?
当C#类标记了[Serializable]特性时,ASP.NET WebAPI默认使用的Json.NET(Newtonsoft.Json)序列化器会切换行为:优先序列化类的字段而非公开属性。你的类里的公开属性对应的是编译器自动生成的私有字段(比如_Location、_Medium),但前端传递的JSON键是属性名(比如Medium),两者命名不匹配,导致无法正确绑定值。
另外你的SomeLocationInfo类构造函数是私有(默认无访问修饰符即为private),这也会让序列化器难以正常创建实例并初始化属性,进一步加剧了绑定失败的问题。
额外注意:前端传的字段名和后端属性还存在不匹配(比如前端SampleLocation对应后端Location,前端ParameterPairs对应后端ParameterPairsInfo),这也是需要修正的点——移除特性后能正常工作,是因为Json.NET默认会处理属性映射,但带[Serializable]时这个逻辑被覆盖了。
无需新建类的复用方案
方案1:用特性覆盖[Serializable]的序列化行为
在类上添加[JsonObject(MemberSerialization.OptIn)],并给每个需要绑定的属性加上[JsonProperty],强制Json.NET使用属性级序列化,同时修正构造函数为public:
[Serializable] [JsonObject(MemberSerialization.OptIn)] public class SomeLocationInfo { [JsonProperty] public string Location { get; set; } [JsonProperty] public string Medium { get; set; } [JsonProperty] public List<ParameterPairs> ParameterPairsInfo { get; set; } public SomeLocationInfo() { ParameterPairsInfo = new List<ParameterPairs>(); } } [Serializable] [JsonObject(MemberSerialization.OptIn)] public class ParameterPairs { [JsonProperty] public string Parameter { get; set; } [JsonProperty] public string Units { get; set; } }
同时调整前端请求的字段名,和后端属性完全对应:
const locationData = { Location: locationName, // 把SampleLocation改成Location Medium: mediumName, ParameterPairsInfo: [{ // 把ParameterPairs改成ParameterPairsInfo Parameter: parameterName, Units: unitAmount }] };
方案2:全局配置Json.NET忽略[Serializable]特性
在WebAPI的WebApiConfig.cs的Register方法中添加全局序列化设置,让所有带[Serializable]的类都按属性序列化:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 其他配置... // 忽略Serializable特性,强制使用属性序列化 config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = true }; } }
这个方法无需修改每个类的特性,一劳永逸。同样需要修正前端字段名和后端属性的匹配问题,以及把SomeLocationInfo的构造函数改为public。
方案3:补充DataContract特性兼容旧代码
如果旧WebAPI代码使用DataContractSerializer,可以给类添加[DataContract]和[DataMember]特性,同时保留[Serializable],这样新旧序列化器都能正确处理:
[Serializable] [DataContract] public class SomeLocationInfo { [DataMember] public string Location { get; set; } [DataMember] public string Medium { get; set; } [DataMember] public List<ParameterPairs> ParameterPairsInfo { get; set; } public SomeLocationInfo() { ParameterPairsInfo = new List<ParameterPairs>(); } } [Serializable] [DataContract] public class ParameterPairs { [DataMember] public string Parameter { get; set; } [DataMember] public string Units { get; set; } }
这种方式既能满足旧代码的序列化需求,又能让新WebAPI的Json.NET正确绑定属性值。
内容的提问来源于stack exchange,提问作者Joshua Gulledge

