2012-04-12 34 views
57

Al usar MVC, devolver Jho adhoc fue fácil.Devolver tipos anónimos con API web

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

Estoy buscando esta funcionalidad con la nueva API web.

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

Esto produce una excepción como el DataContractJsonSerializer no puede manejar los tipos anónimos.

He sustituido esto con este JsonNetFormatter basado en Json.Net. Esto funciona si uso

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

pero no veo el punto de utilizar la API de Web si no estoy volviendo HttpResponseMessage, sería mejor de pegarse con vainilla MVC. Si trato y uso:

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

Se serializa todo el HttpResponseMessage.

¿Alguien me puede guiar a una solución donde puedo devolver tipos anónimos dentro de un HttpResponseMessage?

Respuesta

67

Esto no funciona en la versión Beta, pero lo hace en la última bits (construido a partir de http://aspnetwebstack.codeplex.com), por lo que probablemente sea el camino para RC. Usted puede hacer

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

Esto no parece ser el caso en la versión actual. Recibo un HTTP 500 cuando ejecuto algo como lo anterior. – CodeMonkeyKing

+0

Funcionando bien para mí en 4.0 RTM. – Snixtor

+14

Una nota importante: solo el serializador json predeterminado puede manejar la serialización de objetos anónimos. El serializador xml predeterminado producirá un error, por lo que debe asegurarse de devolver los objetos anónimos que sus clientes saben que deben enviar para aceptar: application/json en el encabezado. Los navegadores como Chrome tienden a solicitar xml de manera predeterminada, así que solo un aviso. – Despertar

1

Debería poder hacer que esto funcione si usa genéricos, ya que le dará un "tipo" para su tipo anónimo. A continuación, puede vincular el serializador a eso.

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

Si no hay DataContract o DataMebmer atributos en su clase, se va a caer de nuevo en la serialización de todas las propiedades públicas, que deben hacer exactamente lo que estás buscando.

(que no tendrá la oportunidad de probar esto hasta el día de hoy, quiero saber si algo no funciona.)

3

se puede utilizar para este JSONObject:

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

return new HttpResponseMessage<JsonObject>(json); 
2

También puede probar:

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()); 
3

Se podría utilizar un ExandoObject.(añadir using System.Dynamic;)

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

Usted puede encapsular objeto dinámico en la devolución de objeto como

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

y luego en WebAPI; hacer algo como:

[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; 
} 
10

Esta respuesta puede venir poco tarde, pero a partir de hoy WebApi 2 ya está fuera y ahora es más fácil hacer lo que quiera sólo tendría que hacer:

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

y a lo largo de la tubería se serializará a xml o json de acuerdo con las preferencias del cliente (el encabezado Accept). Espero que esto ayude a cualquiera a tropezar con esta pregunta

+0

No lo hago para mí – doker

+0

@doker ¿Qué versión de WebApi estás usando? Acabo de pegar ese código desde mi controlador usando VS 2015 y WebApi2 – Luiso

+0

5.2 .3 y terminé eliminando el formateador xml porque la mayoría de los objetos devueltos no se serializarían en xml de todos modos. – doker