2014-06-20 18 views
6

Davvero in difficoltà con qualcosa spero che le persone qui possano aiutarti. Sto scrivendo un'API RESTful in Web API 2. Ogni volta che invio una richiesta a questo servizio, la risposta viene inviata costantemente con uno Content-Type di text/plain. Ovviamente questo non va bene, la mia risposta deve essere Content-Type di application/json. Ho provato alcuni suggerimenti che ho trovato da Google, ma non credo di capire l'intera immagine.Web API 2 restituendo testo/risposte semplici

C'è qualcosa di speciale che devo fare per far rispondere il mio servizio web con il contenuto di application/json? Nota che voglio che funzioni a livello globale su tutta l'app, quindi non sono in grado di modificare una determinata risposta e impostare il suo tipo di contenuto: voglio che questo sia un comportamento predefinito per l'intero servizio web: Se una richiesta contiene un'intestazione Accept per application/json Desidero che il mio servizio Web restituisca quello Content-Type anziché text/plain.

Modifica per chiarire:

La mia risposta contiene un oggetto chiamato "responseData" che dovrebbe essere serializzato in JSON e inclusa nel corpo. Attualmente sto mettendo insieme la mia risposta in questo modo:

HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, responseData); 
return response; 

responseData è un POCO. Questo get è serializzato correttamente come JSON e restituito nella risposta - l'unica parte mancante è il Content-Type che è impostato erroneamente su "text/plain". Potrei cambiarlo manualmente su ogni singola risposta che compongo, ma voglio configurarlo a livello globale.

+0

L'API in questione restituisce una 'stringa' con contenuti JSON creati da te? – Corey

+0

Controllare questo http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation, http: //msdn.microsoft.com/en-us/magazine/dn574797.aspx , http: //blogs.msdn.com/b/henrikn/archive/2012/04/22/asp-net-web-api-content-negotiation-and-accept-charset.aspx, – malkam

+0

@Corey attualmente la risposta è creato in questo modo: 'HttpResponseMessage response = Request.CreateResponse (HttpStatusCode.OK, responseData);' e quindi restituisco 'response' nella mia azione. Il contenuto di responseData viene serializzato in JSON in modo corretto, ma l'intestazione content-type effettiva è ancora impostata su text/plain :( –

risposta

7

OK, supponendo che la stringa responseData sia una stringa, l'intestazione Content-type sarà text/plain quando si crea lo HttpResponseMessage. Non importa quale sia il contenuto della stringa, poiché non viene fatto alcun tentativo per determinarlo.

La soluzione è quella di creare l'oggetto contenuto appropriato per il vostro messaggio, inizializzato con il tipo di materiale che si sta tornando:

HttpResponseMessage response = new HttpResponseMessage() 
    { 
     Content = new StringContent(
       responseData, 
       Encoding.UTF8, 
       "application/json" 
      ) 
    }; 

Ci sono altri metodi che ammontano a restituire un particolare tipo di oggetto e lasciare che l'API le librerie serializzano su JSON o XML per te come richiesto. Preferisco lasciare che il framework faccia il lavoro per me, dove possibile, ma è così che lo realizzeresti con una stringa che hai creato tu stesso.


Per un risultato solo JSON rigido, rimuovere il formattatore XML dalla configurazione WebAPI e restituire il POCO.

In App_Start\WebApiConfig.cs, aggiungere il seguente al metodo WebApiConfig.Register:

config.Formatters.Remove(config.Formatters.XmlFormatter); 

E per il vostro API:

public class MyObject 
{ 
    public bool result; 
    public string reason; 
} 

public class TestController : ApiController 
{ 
    public MyObject GetData() 
    { 
     MyObject result = new MyObject { result = "true", reason = "Testing POCO return" }; 
     return result; 
    } 
} 

mi sono imbattuto questo e chiesto /api/Test da Chrome, che non ha nemmeno parlare application/json nell'intestazione Accept.Ecco la risposta intestazioni fino colpisce Content-Type:

HTTP/1.1 200 OK 
Cache-Control: no-cache 
Pragma: no-cache 
Content-Type: application/json; charset=utf-8 

E il corpo:

{"result":true,"reason":"Testing POCO return"} 

Da quando ho disabilitato XML è stabilizzato a JSON.

+0

Come accennato nella mia domanda, sto cercando di trovare un modo globale per impostare questo, piuttosto che dover definire esplicitamente il tipo di contenuto per ogni risposta che creo.Il mio testo era un po 'poco chiaro forse - Ho modificato il mio OP per chiarire, spero, un paio di punti –

+0

Hai provato a restituire l'oggetto stesso ? 'HttpResponseMessage' va bene quando vuoi un maggiore controllo sui singoli ritorni, ma puoi restituire un POCO e lasciare che le librerie si occupino della serializzazione per te - JSON o XML, a seconda di' Accept' h eader nella richiesta. – Corey

+0

Suppongo che il problema sia che avrò ancora la necessità di restituire 404 o 500 ecc. Se qualcosa va storto - è ancora possibile utilizzare l'approccio descritto? –

0

Aggiungere quanto segue al file Global.asax.

protected void Application_Start() 
{ 

JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); 
serializerSettings.Converters.Add(new IsoDateTimeConverter()); 
var jsonFormatter = new JsonNetFormatter(serializerSettings); 
jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
GlobalConfiguration.Configuration.Formatters.Insert(0, jsonFormatter); 

} 
+0

Si presume che qualcuno abbia creato un JsonNetFormatter di qualche tipo e non funzioni senza tale comprensione o ulteriori dettagli. – Suamere

0

Un'altra possibile fonte del problema descritto è che ci può essere un'autorizzazione reindirizzare in gioco come è stato il caso per noi quando uno degli ingegneri pensato di riutilizzare l'autenticazione utente per un api.

Ciò significa che le richieste in entrata sono state reindirizzate a una pagina di accesso che era la risposta text/html che non è stata analizzata da ReadAsync<>. Un errore stupido per essere sicuro, ma non facile da individuare.

La soluzione in questo caso era rimuovere l'autenticazione utente e implementare l'autenticazione basata su HMAC per l'API.

Problemi correlati