2015-02-25 2 views
1

У меня есть верблюжий корпус, сконфигурированный как выход JSON по умолчанию из библиотеки Newtonsoft. В следующей строке вызывается во время Application_Start:Newtonsoft JSON по желанию изменить кожух полезной нагрузки WebAPI 2

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

Все REST Javascript звонки на WebAPIs (с использованием WebAPI 2) работают нормально и вернуть верблюд обсаженных JSON строки клиенту.

Теперь я использую JTable управления (http://www.jtable.org) на одном из моих веб-страницах, и этот контроль требует, чтобы JSON полезной нагрузки возвращается в Proper Case. Итак, вопроскак можно изменить WebAPI, чтобы вернуть полезную нагрузку на полезный случай JSON, даже если конфигурация по умолчанию через Application_Start установлена ​​на верблюжьем корпусе, не изменяя значения глобального значения по умолчанию? Мне нужен правильный случай. Полезная нагрузка JSON возвращается только для этого одного вызова 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; 
} 

Проблема здесь в том, что теперь я не могу вернуться к дефолту ГорбатыйРегистр форматирования, так как метод вернулся к тому времени.

Любые другие предложения?

+0

возможно дубликат [Return camelCased JSON из веб-API] (HTTP: // stackoverflow.com/questions/26474436/return-camelcased-json-from-web-api) – dotctor

+0

Если у вас есть три метода, скажем A, B и C, нужна ли вам динамическая модификация дела по любым/всем методам или вам нужно всего лишь запустить Паскаль для метода C всегда? –

+0

Мне нужно запустить Pascal case только для метода C (всегда). Другие методы должны продолжать использовать настройки по умолчанию для верблюжьего случая. – sandor

ответ

1

Вы можете позвонить Request.CreateResponse с the overload that takes a MediaTypeFormatter и передать в new JsonMediaTypeFormatter() аналогично тому, как вы настраивали его глобально, но специально для этого одного метода. И, конечно же, вы можете указать любые SerializerSettings, которые вы хотите. Вероятно, было бы лучше сохранить частный статический экземпляр этого в вашем контроллере, чтобы вы не каждый раз добавляли его.

+0

Дэвид, спасибо за предложение. Я использовал его, и он работает **. Полагаю, я был слишком зациклен на попытке выполнить это, используя библиотеку Newtonsoft.Json. Наверное, я надеялся, что у него будет какой-то тип переопределения MediaTypeFormatter, который можно использовать для изменения способа загрузки полезных данных JSON в зависимости от того, какой вызов WebAPI вызывается. – sandor

+0

Если вы хотите контролировать, какие параметры сериализации используются во многих методах API в централизованном месте, вы должны задуматься о написании собственного 'MediaTypeFormatter'. Затем вы можете проверить запрос и иметь карту сериализатора для маршрутизации или что-то в этом направлении. –

+0

@sandor Затем отметьте это как принятое решение. Вы оба заслуживаете репутацию за это. –

0

Вам необходимо явно сериализовать ваш 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 
} 
+0

Прежде всего, спасибо за ваш ответ. Я попытался найти решение с последней версией Newtonsoft.Json (6.0.0.0). Я не смог найти «JsonRequestBehavior». Кроме того, комментарий [// Это сериализуется явно, ** до того, как ** WebApi вызывает сериализатор по умолчанию] немного смутил меня. Если сериализатор Json() вызывается перед сериализатором WebAPI, то в чем смысл? Не будет ли сериализатор WebAPI просто превзойти все, что сделал Json()? Я не смог скомпилировать код и проверить. См. Мой ответ ниже предложения Дэвида Педена. – sandor

0

Вот мой последний метод WebAPI, который работает так, как мне нужно. Слишком плохо, что я не смог получить эту функциональность через библиотеку Newtonsoft.Json, поэтому метод будет возвращать бизнес-объект, а не объект ответа. Для ясности я удалил код из класса. (т. е. отслеживание, комментарии и т. д.).

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); 
     } 
    } 
} 

Ниже мое решение с OkNegotiatedContentResult <> в соответствии с рекомендациями Давида, поскольку я использую WebAPI 2.

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); 
     } 
    } 
} 
+0

'JsonMediaTypeFormatter' использует Json.Net под капотом. Сериализованный ответ тот же, независимо от того, какой тип возвращаемого значения используется для вашего метода API. Не знаете, почему вам не нравится это решение ... –

+0

Я бы также рекомендовал явно установить параметры сериализатора, чтобы поддерживать корпус, который вы хотите, чтобы a.) Ваше намерение было объявлено и b.), Если значение по умолчанию было когда-либо измените, ваш код не сломается. –

+0

И еще одно: если вы используете Web API 2, вы можете вернуть «OkNegotiatedContentResult » (см. [Здесь] (https://msdn.microsoft.com/en-us/library/dn308866 (v = vs .118) .aspx)), чтобы получить строго типизированный ответ. –

Смежные вопросы