我只想为我的一个 Controller 更改传入请求的反序列化格式。所以我将它添加到我的 Global.asax 中,它工作得很好:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
但它将更改应用于所有 Controller 。我只想将它应用于我的一个 Controller 。我还找到了this回答,我根据那个写了这段代码:
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
var formatter = controllerSettings.Formatters.OfType<JsonMediaTypeFormatter>().Single();
controllerSettings.Formatters.Remove(formatter);
formatter = new JsonMediaTypeFormatter
{
SerializerSettings = { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } }
};
controllerSettings.Formatters.Add(formatter);
}
但不幸的是,它仅适用于序列化输出。有没有办法定义它以反序列化输入?
请您参考如下方法:
您可以使用棘手的媒体类型格式化程序来完成所需的工作。通常自定义格式化程序会覆盖方法 CanReadType()/CanWriteType() 和 ReadFromStreamAsync()/WriteToStreamAsync()。 CanWriteType() 在您的情况下应始终返回 false 因为您对自定义序列化不感兴趣。关于反序列化,您可以使用标准的 JsonMediaTypeFormatter(通过继承或聚合)并将其 SerializerSettings 设置为使用 SnakeCaseNamingStrategy:
public class SnakeCaseJsonFormatter : JsonMediaTypeFormatter
{
public SnakeCaseJsonFormatter()
{
SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
}
public override bool CanWriteType(Type type)
{
return false;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
throw new NotImplementedException();
}
}
剩下的部分是在 Controller 级别应用这种自定义格式化程序。您可以使用实现 IControllerConfiguration 接口(interface)的自定义属性来执行此操作。在 Initialize() 方法中,将您的自定义格式化程序设置在第一个位置,以便它优先于标准 JsonMediaTypeFormatter。您不应删除标准的 JsonMediaTypeFormatter,因为它将处理数据序列化:
public sealed class SnakeCaseNamingAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
controllerSettings.Formatters.Insert(0, new SnakeCaseJsonFormatter());
}
}
现在只要在你想要的 Controller 上应用这个属性,瞧:
[SnakeCaseNaming]
public class ValuesController : ApiController
