Skip to main content
 首页 » 编程设计

c#之在每个 Controller 的 WebAPI 上强制 SnakeCase 反序列化

2024年02月27日31del

我只想为我的一个 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