2012-04-12 14 views
57

Quando si utilizza MVC, restituire adhoc Json è stato facile.Restituzione di tipi anonimi con Web API

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

Sto cercando questa funzionalità con la nuova API Web.

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

Questo genera un'eccezione come il DataContractJsonSerializer non può gestire tipi anonimi.

Ho sostituito questo con questo JsonNetFormatter basato su Json.Net. questo funziona se uso

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

ma non vedo il punto di usare API Web se non sto tornando HttpResponseMessage, sarei meglio attaccare con vaniglia MVC. Se provo e uso:

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

E serializza l'intero HttpResponseMessage.

Qualcuno può guidarmi a una soluzione in cui posso restituire tipi anonimi all'interno di un HttpResponseMessage?

risposta

67

Questo non funziona nella versione beta, ma lo fa nel più recente bit (costruiti da http://aspnetwebstack.codeplex.com), quindi sarà probabilmente il modo per RC. Si può fare

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

Questo non sembra essere il caso nella versione corrente. Ricevo un HTTP 500 quando eseguo qualcosa come sopra. – CodeMonkeyKing

+0

Funzionante per me in 4.0 RTM. – Snixtor

+14

Una nota importante, solo il serializzatore json predefinito può gestire la serializzazione di oggetti anonimi. Il serializzatore xml predefinito genererà un errore, quindi assicurati di restituire oggetti anonimi che i tuoi clienti sanno per inviare accettare: application/json in header. Anche i browser come Chrome tendono a richiedere xml per impostazione predefinita, quindi basta un avviso. – Despertar

1

Dovresti essere in grado di farlo funzionare se usi i generici, in quanto ti darà un "tipo" per il tuo tipo anonimo. È quindi possibile associare il serializzatore a quello.

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

Se non ci sono DataContract o DataMebmer attributi tua classe, sarà ripiegare su serializzazione di tutte le proprietà pubbliche, che dovrebbe fare esattamente quello che stai cercando.

(io non avranno la possibilità di testare questo fino al più tardi oggi, fatemi sapere se qualcosa non funziona.)

3

è possibile utilizzare JsonObject per questo:

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

return new HttpResponseMessage<JsonObject>(json); 
2

Si può anche provare:

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

Si potrebbe utilizzare un ExandoObject.(aggiungi using System.Dynamic;)

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

È possibile incapsulare oggetto dinamico in restituendo l'oggetto come

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

e poi in WebAPI; fare qualcosa di simile:

[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

Questa risposta può venire po 'in ritardo, ma a partire da oggi WebApi 2 è già fuori e ora è più facile fare ciò che si desidera si dovrebbe solo avere a che fare:

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

e lungo la pipeline verrà serializzato su xml o json in base alle preferenze del cliente (l'intestazione Accept). Spero che questo aiuti chiunque inciampa su questa domanda

+0

Non lo faccio per me – doker

+0

@doker Quale versione di WebApi stai usando, ho appena incollato quel codice dal mio controller usando VS 2015 e WebApi2 – Luiso

+0

5.2 .3 e ho finito per rimuovere xml formater perché la maggior parte degli oggetti restituiti non sarebbero serializzati in xml comunque. – doker