Newtonsoft JSON 可选地更改负载大小写 WebAPI 2

Newtonsoft JSON optionally change payload casing WebAPI 2

我将驼峰式大小写配置为 Newtonsoft 库的默认 JSON 输出。在 Application_Start 期间调用以下行:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

对 WebAPI 的所有 javascript REST 调用(使用 WebAPI 2)工作正常,return 驼峰 JSON 字符串到客户端。

现在,我在我的一个网页上使用 jTable 控件 (http://www.jtable.org),此控件要求 JSON 有效载荷 returned in Proper案例所以问题是 即使默认配置通过 Application_Start 在不更改全局默认设置的情况下设置为驼峰式大小写? 我需要正确的大小写 JSON 有效负载 return 只为应用程序中的这个 WebAPI 调用编辑。

我试过 [http://fizzylogic.nl/2014/07/30/changing-the-casing-of-json-properties-in-asp-dot-net-web-api/] 这个,但我无法让 ActionFilterAttribute.OnActionExecuting 开火。所以解决方案没有奏效。

我还在WebAPI方法中添加了下面这行代码

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new JsonContractResolver(new JsonMediaTypeFormatter());

这可行,但正确大小写现在成为其他 WebAPI 调用的默认格式。

这是 WebAPI 片段

public JTableDtoImpl Get(int id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = "") {
        List<MobileOrderModel> orders = _svc.GetMobileOrders(id);
        var dto = new JTableDtoMobileOrdersImpl(orders, jtStartIndex, jtPageSize) {
            Message = string.Format("DataSource:{0}", _svc.DataSource)
        };
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new JsonContractResolver(new JsonMediaTypeFormatter());
        return dto;
}

这里的问题是我现在无法恢复为默认的驼峰式大小写格式,因为那时该方法已经 return 编辑了。

还有其他建议吗?

您需要显式序列化您的 JSON,而不是返回一个对象并让 WebApi 为您序列化它。尝试类似的东西:

public JSonResult Get(int id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = "")
{
   List<MobileOrderModel> orders = _svc.GetMobileOrders(id);
   var dto = new JTableDtoMobileOrdersImpl(orders, jtStartIndex, jtPageSize) {
      Message = string.Format("DataSource:{0}", _svc.DataSource)
   };
   return Json(dto, JsonRequestBehavior.AllowGet); // This serializes explicitly, before WebApi invokes the default serializer
}

您可以使用 the overload that takes a MediaTypeFormatter 调用 Request.CreateResponse 并传入 new JsonMediaTypeFormatter() ,这与您在全局设置它的方式类似,但专门用于此方法。当然,您可以指定任何您想要的 SerializerSettings。最好在您的控制器中保留它的私有静态实例,这样您就不会 new 每次都启动它。

这是我的最终 WebAPI 方法,它可以按我需要的方式工作。很遗憾我无法通过 Newtonsoft.Json 库获得此功能,因此该方法将返回业务对象而不是响应对象。为了清楚起见,我从 class 中删除了代码。 (即:跟踪、评论等)。

public class MobileOrdersController : ApiController {
    private static readonly MobileOrdersService _svc = new MobileOrdersService();
    private static readonly MediaTypeFormatter _properCaseFormatter = new JsonMediaTypeFormatter{
        SerializerSettings = new JsonSerializerSettings {
            ContractResolver = new DefaultContractResolver()
        }
    };

    [Authorize][HttpGet]
    public HttpResponseMessage GetCustomerMobileOrders(int id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = "") {
        try {
            List<MobileOrderModel> orders = _svc.GetMobileOrders(id);
            var dto = new JTableDtoMobileOrdersImpl(orders, jtStartIndex, jtPageSize) {
                Message = string.Format("DataSource:{0}", _svc.DataSource)
            };
            return Request.CreateResponse(HttpStatusCode.OK, dto, _properCaseFormatter);
        } catch (Exception ex) {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
        }
    }
}

以下是我使用 WebAPI 2 时大卫推荐的 OkNegotiatedContentResult<> 解决方案。

public class MobileOrdersController : ApiController {
    private static readonly MobileOrdersService _svc = new MobileOrdersService();
    private static readonly IContentNegotiator _conneg = GlobalConfiguration.Configuration.Services.GetContentNegotiator();
    private static readonly IEnumerable<JsonMediaTypeFormatter> _mediaTypeFormatters = new[] {
        new JsonMediaTypeFormatter {
            SerializerSettings = new JsonSerializerSettings {
                ContractResolver = new DefaultContractResolver()
            }
        }
    };

    [Authorize][HttpGet]
    public IHttpActionResult GetCustomerMobileOrders(int id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = "") {
        try {
            List<MobileOrderModel> orders = _svc.GetMobileOrders(id);
            var dto = new JTableDtoMobileOrdersImpl(orders, jtStartIndex, jtPageSize) {
                Message = string.Format("DataSource:{0}", _svc.DataSource)
            };
            return new OkNegotiatedContentResult<JTableDtoMobileOrdersImpl>(dto, _conneg, Request, _mediaTypeFormatters);
        } catch (Exception ex) {
            return new ExceptionResult(ex, this);
        }
    }
}