我有一个Web Api控制器,如下所示
public class HomeController : ApiController
{
....
[HttpPost]
[Route("api/Add")]
public IHttpActionResult Add(Employee emp)
{
...
}
}
[Serializable]
public class Employee
{
public string Name { get; set; }
}
仅当从Employee类中删除[Serializable]
属性时,Http Post请求中发送的参数才会在Controller中映射。如果我添加该属性,则Name
类中的属性Employee
的值始终为null
当模型类标记为[Serializable]
时,有人可以解释什么是错误的吗?
答案 0 :(得分:2)
要理解为什么会发生这种情况,您需要了解SerializableAttribute
的确切含义。这意味着可以通过序列化其公共和私有字段 (即,不是其属性)来序列化此类。该属性的日期来自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]
。
Web {的current version使用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,请确保使用here中指定的XmlSerializer
。
如果您在MVC 4 Web API中使用JSON和Json.NET,则可以在Application_Start
中的Global.asax.cs中设置IgnoreSerializableAttribute = true
:
protected void Application_Start()
{
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
new DefaultContractResolver { IgnoreSerializableAttribute = true };
}
或者,只需删除[Serializable]
,除了BinaryFormatter
之外,你真的不需要它。