Как вернуть несколько типов объектов для ApiControllers

Я обновил свой проект, чтобы использовать ASP.NET MVC4 из MVC3. Теперь мой контроллер использует ApiController вместо контроллеров. Раньше я использовал функцию как:

 public JsonResult GetPermissions(string portfolioId)
 {
     //DO THE DATA FETCH
     return Json(new { PermissionValues = permissionValues,       UserPermissions = userPermissions, OwnerValues = ownerList },JsonRequestBehavior.AllowGet);
 } 

Я хотел бы сделать аналогичную операцию, используя ApiControllers. Я не хочу создавать отдельный объект, в котором объект будет иметь 3 свойства [поскольку я возвращаю 3 списка]. Я пытался использовать HttpResponseMessage<Object> в качестве возвращаемого типа функции, но, похоже, не работает.

    public HttpResponseMessage<Object> GetPermissions(string portfolioId)
    {
      //DO THE DATA FETCH
      HttpResponseMessage<Object> response = new HttpResponseMessage<Object>(new { Users = listedUsers, PermissionValues = permissionValues });
      return response;
    }

Любые идеи ?


person Anirban    schedule 24.05.2012    source источник


Ответы (1)


Основная проблема, с которой вы столкнулись, заключается в том, что сериализатор по умолчанию для ответов json в бета-битах не может сериализовать анонимные типы. Вам нужно использовать средство форматирования, например, основанное на Json.NET (которое будет встроено в следующем выпуске). Чтобы это работало с бета-версией, ваш код изменится на что-то вроде этого:

public HttpResponseMessage Get()
{
    var content = new { Users = new List<string> { "John", "Mary" }, Permissions = new List<string> { "User", "Admin" } };
    return new HttpResponseMessage<object>(content, new[] { new JsonNetFormatter() });
}

Что даст такой ответ:

{"Users":["John","Mary"],"Permissions":["User","Admin"]}

Как только RC будет доступен, ваш существующий код должен работать нормально.

Обновлять:

Чтобы этот код скомпилировался, вам нужна реализация для JsonNetFormatter. Вы можете найти реализацию, предоставленную Хенриком (MSFT) по адресу http://code.msdn.microsoft.com/Using-JSONNET-with-ASPNET-b2423706#content или из проекта WebApiContrib по адресу https://github.com/WebApiContrib/WebAPIContrib/blob/master./src/WebApiContrib.Formatting.JsonNet/JsonNetFormatter.cs .

Обратите внимание, что они оба страдают от одной и той же ошибки в методе OnWriteToStreamAsync. Эти реализации закрывают базовый поток. Вам нужно изменить операторы использования, чтобы они выглядели следующим образом:

using (var jsonTextWriter = new JsonTextWriter(new StreamWriter(stream, Encoding)) { CloseOutput = false })

Хенрик отметил это в своем блоге, но ни его пример, ни образец contrib не были обновлены, и у меня просто не было времени внести исправление в проект contrib. ;)

person David Peden    schedule 24.05.2012
comment
Спасибо за ваш ответ. У меня есть вопрос по этому поводу. Я добавил ссылку на Newtonsoft.Json, но когда я пытаюсь построить, выдается исключение. Не удалось найти тип или имя пространства имен «JsonNetFormatter». - person Anirban; 24.05.2012
comment
Плохая идея вставлять форматтер внутрь HttpResponseMessage. Conneg не будет работать с этой реализацией. Если OP не нужен Conneg, зачем использовать Web API? просто верните его с помощью MVC JsonResult. С другой стороны, этот код сломается для следующего продукта, который не содержит общих сообщений ответа и запроса. - person tugberk; 27.05.2012
comment
@tugberk Я согласен с вами в том, что, вообще говоря, предпочтительнее воспользоваться преимуществами согласования контента. Однако OP явно намеревался явно вернуть ответ json. - person David Peden; 27.05.2012
comment
@DPeden, тогда нет ничего плохого в JsonResult, поскольку OP использует MVC. этот пример полностью противоречит основному принципу веб-API ASP.NET. Если целью является только возврат ответа Json для каждого запроса, я предлагаю удалить все остальные средства форматирования, кроме JsonMediaTypeFormatter. - person tugberk; 28.05.2012