c# - 如果模型类标记为可序列化,则参数值不会映射到 Web API 中

标签 c# serialization asp.net-web-api

我有一个 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 没有愚蠢的支持字段属性名称。

要解决此问题,您有以下选择:

  1. data contract attributes 注释你的类。这些取代 [Serializable]对于所有支持它的序列化器:

    [Serializable]
    [DataContract]
    public class Employee
    {
        [DataMember]
        public string Name { get; set; }
    }
    
  2. 如果您使用 XML,请确保使用 XmlSerializerhere 中指定.

  3. 如果您在 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 };
    }
    
  4. 或者,只需删除 [Serializable] ,除了 BinaryFormatter 之外,你真的不需要它。 .

关于c# - 如果模型类标记为可序列化,则参数值不会映射到 Web API 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33215188/

相关文章:

c# - 捕获第二次鼠标移动

c# - 有没有办法在 C# 中伪造注册表项?

c# - c# 中 [Serializable] 和 [Serializable()] 之间有区别吗?

c# - 在 C# 中反序列化 SOAP 数组

python - 如何在 DRF 中序列化自定义用户模型

c# - 如何在 EF 中选择按日期分组的多个计数

c# - 在存储对象中调用方法

authentication - Web api 中的基本身份验证

c# - SignalR 使用 GlobalHost.ConnectionManager.GetHubContext 从外部集线器调用客户端方法不起作用。但是从集线器内部调用确实

asp.net-mvc - Fiddler 未从 LINQPad 上的 webClient 捕获本地流量