【问题标题】:Web API: Configure JSON serializer settings on action or controller levelWeb API:在操作或控制器级别配置 JSON 序列化程序设置
【发布时间】:2017-06-12 12:07:33
【问题描述】:

很多 SO 线程都涵盖了在应用程序级别覆盖 Web API 的默认 JSON 序列化程序设置。但是如何在操作级别配置其设置?例如,我可能想在我的一个操作中使用驼峰式属性进行序列化,但在其他操作中不使用。

【问题讨论】:

  • 你能不能只制作HttpResponseMessage 手动将内容设置为你想要的json输出?它不像处理全局格式化程序那样整洁,但您仍然可以创建 DRY 助手来处理这些一次性情况。
  • 你考虑过任务的 ActionFilterAttributes 吗?
  • 最好的方法是构建一个 HTTP 模块并根据每个不同操作的需要拦截每个请求和进程。
  • 您会考虑每个控制器而不是每个操作的覆盖吗?
  • @FedericoDipuma 当然,那很好

标签: c# asp.net-web-api json.net


【解决方案1】:

选项 1(最快)

在操作级别,您可以在使用Json 方法时始终使用自定义JsonSerializerSettings 实例:

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        var model = new MyModel();
        return Json(model, settings);
    }
}

选项 2(控制器级别)

您可以创建一个新的 IControllerConfiguration 属性来自定义 JsonFormatter:

public class CustomJsonAttribute : Attribute, IControllerConfiguration 
{
    public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
    {
        var formatter = controllerSettings.Formatters.JsonFormatter;

        controllerSettings.Formatters.Remove(formatter);

        formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings =
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }
        };

        controllerSettings.Formatters.Insert(0, formatter);
    }
}

[CustomJson]
public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        var model = new MyModel();
        return Ok(model);
    }
}

【讨论】:

  • 这正是我正在寻找的,拯救了我的一天,非常感谢 :)
  • 我们需要实例化一个新的格式化程序吗?我们不能调整当前实例,否则更改将应用​​到任何地方?
  • @JobaDiniz 如您所说,如果您更改原始格式化程序的属性,这些更改将影响所有其他控制器
  • 很好的 SerializerSettings 初始化!我不知道那个 C# 功能。
【解决方案2】:

这是上述作为动作属性的实现:

public class CustomActionJsonFormatAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext?.Response == null) return;

        var content = actionExecutedContext.Response.Content as ObjectContent;

        if (content?.Formatter is JsonMediaTypeFormatter)
        {
            var formatter = new JsonMediaTypeFormatter
            {
                SerializerSettings =
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                }
            };

            actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, formatter);
        }
    }
}

public class MyController : ApiController
{
    [CustomActionJsonFormat]
    public IHttpActionResult Get()
    {
        var model = new MyModel();
        return Ok(model);
    }
}

【讨论】:

  • 我使用了这段代码,但我给了它一个Type ContractResolverType 属性,然后做了ContractResolver = (IContractResolver)Activator.CreateInstance(ContractResolverType),所以我不必为每个合约解析器类型创建其中一个。在使用中它看起来像这样:[ActionContractResolver(ContractResolverType = typeof(DefaultContractResolver))]
【解决方案3】:

我需要在带有错误详细信息的 json 对象旁边返回 404 状态错误代码。我使用带有新 JsonMediaTypeFormatter 的 WebApi.Content 解决了它。

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        // Configure new Json formatter
        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings =
            {
                TypeNameHandling = TypeNameHandling.None,
                PreserveReferencesHandling = PreserveReferencesHandling.None,
                Culture = CultureInfo.InvariantCulture,
                Formatting = Formatting.Indented,
                NullValueHandling = NullValueHandling.Ignore
            }
        };

        try
        {
            var model = new MyModel();
            return Content(HttpStatusCode.OK, model, formatter);
        }
        catch (Exception err)
        {
            var errorDto = GetErrorDto(HttpStatusCode.NotFound, $"{err.Message}");
            return Content(HttpStatusCode.NotFound, errorDto, formatter);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-01
    • 2020-11-18
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多