我有一个 Web Api Controller ,如下所示
public class HomeController : ApiController
{
....
[HttpPost]
[Route("api/Add")]
public IHttpActionResult Add(Employee emp)
{
...
}
}
[Serializable]
public class Employee
{
public string Name { get; set; }
}
仅当从 Employee 类中删除 [Serialized]
属性时,Http Post 请求中发送的参数才会映射到 Controller 中。如果我添加该属性,Employee
类中的属性 Name
的值始终为 null
当模型类标记为[Serialized]
时,有人可以解释一下出了什么问题吗?
最佳答案
要理解为什么会发生这种情况,您需要理解 SerializableAttribute
的精确含义。 。这意味着这个类可以通过序列化其公共(public)和私有(private)字段(即不是其属性)来序列化。该属性可以追溯到 c# 1.0,当时所有属性都有显式支持字段,最初由 BinaryFormatter
使用。 。那么,当c# 3.0中引入自动实现的属性时,它们是如何序列化的呢?
并非所有序列化器都支持 [Serializable]
,但是那些通过序列化其 hidden backing fields 来序列化自动实现的属性的属性按名称和值。您没有说明您正在使用哪个版本的 Web API,也没有说明数据格式(XML 或 JSON),因此您可能正在使用:
DataContractSerializer
。数据协定序列化器支持[Serializable]
,如 Types Supported by the Data Contract Serializer 中所述。 XML 数据协定序列化器序列化您的Employee
类如下:<Employee> <_x003C_Name_x003E_k__BackingField>My Name</_x003C_Name_x003E_k__BackingField> </Employee>
DataContractJsonSerializer
还序列化支持字段,生成:{"<Name>k__BackingField":"My Name"}
Json.NET 仅当
DefaultContractResolver.IgnoreSerializableAttribute = false
时才会序列化支持字段。 :var employee = new Employee { Name = "My Name" }; var json1 = JsonConvert.SerializeObject(employee, new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = false } }); Console.WriteLine(json1);
还生产
{"<Name>k__BackingField":"My Name"}
。如果没有设置,Json.NET 将忽略该属性。XmlSerializer
忽略[Serializable]
.JavaScriptSerializer
也忽略[Serializable]
.
current version Web API 使用 Json.NET 和 XmlSerializer
,但这是可配置的。早期版本 use the data contract serializers有时甚至是JavaScriptSerializer
.
因此,您的 Name
的原因属性为 null 是因为您正在使用支持 [Serializable]
的序列化器之一并且您发布的 JSON 或 XML 没有愚蠢的支持字段属性名称。
要解决此问题,您有以下选择:
用 data contract attributes 注释你的类。这些取代
[Serializable]
对于所有支持它的序列化器:[Serializable] [DataContract] public class Employee { [DataMember] public string Name { get; set; } }
如果您使用 XML,请确保使用
XmlSerializer
如 here 中指定.如果您在 MVC 4 Web API 中使用 JSON 和 Json.NET,则可以设置
IgnoreSerializableAttribute = true
在 Global.asax.cs 中Application_Start
:protected void Application_Start() { HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = true }; }
或者,只需删除
[Serializable]
,除了BinaryFormatter
之外,你真的不需要它。 .
关于c# - 如果模型类标记为可序列化,则参数值不会映射到 Web API 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33215188/