Повернення анонімних типів за допомогою веб-API


74

При використанні MVC повернути adhoc Json було легко.

return Json(new { Message = "Hello"});

Я шукаю цю функціональність за допомогою нового веб-API.

public HttpResponseMessage<object> Test()
{    
   return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}

Це видає виняток, оскільки DataContractJsonSerializerне може обробляти анонімні типи.

Я замінив це цим JsonNetFormatter на основі Json.Net . Це працює, якщо я використовую

 public object Test()
 {
    return new { Message = "Hello" };
 }

але я не бачу сенсу використовувати веб-API, якщо я не повернусь HttpResponseMessage, мені було б краще дотримуватися ванільного MVC. Якщо я спробую використати:

public HttpResponseMessage<object> Test()
{
   return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}

Це серіалізує ціле HttpResponseMessage.

Хто-небудь може направити мене до рішення, де я можу повернути анонімні типи в межах HttpResponseMessage?

Відповіді:


85

Це не працює у бета-версії, але працює в останніх версіях (побудованих з http://aspnetwebstack.codeplex.com ), тому, швидше за все, це шлях для RC. Ви можете зробити

public HttpResponseMessage Get()
{
    return this.Request.CreateResponse(
        HttpStatusCode.OK,
        new { Message = "Hello", Value = 123 });
}

1
Здається, це не так у поточному випуску. Я отримую HTTP 500, виконуючи щось на кшталт вище.
CodeMonkeyKing

Мені добре працює у 4.0 RTM.
Snixtor

16
Важливе зауваження: лише серіалізатор json за замовчуванням може обробляти серіалізацію анонімних об’єктів. За замовчуванням серіалізатор xml виведе помилку, тому будьте впевнені, якщо ви повернете анонімні об’єкти, які ваші клієнти знатимуть для надсилання accept: application / json у заголовку. Браузери, як Chrome, як правило, також за замовчуванням вимагають xml, тому просто
зверніть увагу

17

Ця відповідь може прийти трохи пізно, але станом на сьогодні WebApi 2вже немає, і тепер легше робити те, що ви хочете, вам просто потрібно було б зробити:

public object Message()
{
    return new { Message = "hello" };
}

і вздовж трубопроводу, буде серіалізовать в xmlабо в jsonвідповідно до своїх уподобань клієнта ( Acceptзаголовок). Сподіваюся, це допомагає комусь натрапити на це питання


@doker Яку версію WebApi ви використовуєте, я щойно вставив цей код із свого контролера за допомогою VS 2015 та WebApi2
Луїсо,

5.2.3, і в підсумку я видалив xml formater, оскільки більшість повернутих об'єктів все одно не серіалізуються в xml.
doker

@doker у вашому випадку тоді, коли ви намагаєтесь зробити те, що я запропонував, що відбувається? ти отримуєш Exception?
Луїсо

9

У веб-API 2 ви можете використовувати новий IHttpActionResult, який є заміною HttpResponseMessage, а потім повернути простий об'єкт Json: (Подібне до MVC)

public IHttpActionResult GetJson()
    {
       return Json(new { Message = "Hello"});
    }

4
Найкраща відповідь для мене. Мені потрібен спосіб повернути тонкий JSON з веб-API Action без створення додаткових матеріалів у різних місцях / збірках. Працює як шарм! Дякую.
Олексій Матвєєв

7

Ви можете використовувати JsonObject для цього:

dynamic json = new JsonObject();
json.Message = "Hello";
json.Value = 123;

return new HttpResponseMessage<JsonObject>(json);

5

Ви можете використовувати ExandoObject . (додати using System.Dynamic;)

[Route("api/message")]
[HttpGet]
public object Message()
{
    dynamic expando = new ExpandoObject();
    expando.message = "Hello";
    expando.message2 = "World";
    return expando;
}

3

Ви також можете спробувати:

var request = new HttpRequestMessage(HttpMethod.Post, "http://leojh.com");
var requestModel = new {User = "User", Password = "Password"};
request.Content = new ObjectContent(typeof(object), requestModel, new JsonMediaTypeFormatter());


2

Ви повинні мати змогу змусити це працювати, якщо ви використовуєте дженерики, оскільки це дасть вам "тип" для вашого анонімного типу. Потім до цього можна прив’язати серіалізатор.

public HttpResponseMessage<T> MakeResponse(T object, HttpStatusCode code)
{
    return new HttpResponseMessage<T>(object, code);
}

Якщо у вашому класі немає атрибутів DataContractабо DataMebmerатрибутів, він повернеться до серіалізації всіх загальнодоступних властивостей, які повинні робити саме те, що ви шукаєте.

(Я не зможу перевірити це до сьогоднішнього дня, повідомте мене, якщо щось не вийде.)


0

Ви можете інкапсулювати динамічний об'єкт у повертається об'єкт типу

public class GenericResponse : BaseResponse
{
    public dynamic Data { get; set; }
}

а потім у WebAPI; зробити щось на зразок:

[Route("api/MethodReturingDynamicData")]
[HttpPost]
public HttpResponseMessage MethodReturingDynamicData(RequestDTO request)
{
    HttpResponseMessage response;
    try
    {
        GenericResponse result = new GenericResponse();
        dynamic data = new ExpandoObject();
        data.Name = "Subodh";

        result.Data = data;// OR assign any dynamic data here;// 

        response = Request.CreateResponse<dynamic>(HttpStatusCode.OK, result);
    }
    catch (Exception ex)
    {
        ApplicationLogger.LogCompleteException(ex, "GetAllListMetadataForApp", "Post");
        HttpError myCustomError = new HttpError(ex.Message) { { "IsSuccess", false } };
        return Request.CreateErrorResponse(HttpStatusCode.OK, myCustomError);
    }
    return response;
}

0
public IEnumerable<object> GetList()
{
    using (var context = new  DBContext())
    {
        return context.SPersonal.Select(m =>
            new  
            {
                FirstName= m.FirstName ,
                LastName = m.LastName
            }).Take(5).ToList();               
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.