web-dev-qa-db-fra.com

Comment forcer l'API Web ASP.NET à renvoyer des données JSON ou XML en fonction de mes entrées?

J'essaie d'obtenir les données XML ou JSON de sortie en fonction de mon entrée. J'ai utilisé le code d'API WEB ci-dessous mais je n'ai pas pu obtenir la sortie exacte.

public string Get(int id)
{
    if (GlobalConfiguration.Configuration.Formatters.XmlFormatter == null)
    {
        GlobalConfiguration.Configuration.Formatters.Add(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
    }
    if (GlobalConfiguration.Configuration.Formatters.JsonFormatter == null)
    {
        GlobalConfiguration.Configuration.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
    }
    if (id == 1)
    {
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);                
        GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;                
    }
    else
    {
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;
    }
    return "value";
}
40

Ajoutez le code ci-dessous app_start événement dans global.asax fichier. Dans l'API URL, ajoutez la chaîne de requête:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(
    new QueryStringMapping("type", "json", new MediaTypeHeaderValue("application/json")));

GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(
    new QueryStringMapping("type", "xml", new MediaTypeHeaderValue("application/xml")));

par exemple.:

for xml : http://localhost:49533/api/?type=xml

for json: http://localhost:49533/api/?type=json
78
vijayjan15

Ce que vous essayez de faire ne fonctionnera pas dans un environnement multithread. Vous ne pouvez pas ajouter ou supprimer de la collection de formateurs sur une base par demande. Voici une meilleure façon d'accomplir ce que vous voulez.

public HttpResponseMessage Get(int id)
{
    Foo foo = new Foo();
    var content = new ObjectContent<Foo>(foo,
                    ((id == 1) ? Configuration.Formatters.XmlFormatter :
                                Configuration.Formatters.JsonFormatter));
    return new HttpResponseMessage()
    {
         Content = content
    };
}
9
Badri

J'ai examiné cela un peu plus et trouvé votre réponse dans n autre message :

public HttpResponseMessage Get(int id)
{
    string content = "value";

    if (id == 1)
    {
        return Request.CreateResponse<string>(HttpStatusCode.OK, content, Configuration.Formatters.JsonFormatter);
    }

    return Request.CreateResponse<string>(HttpStatusCode.OK, content, Configuration.Formatters.XmlFormatter);
}
8
jamiebarrow

Il fonctionne également pour forcer les en-têtes d'acceptation. Excellente option si vous ne revenez pas toujours HttpResponseMessage's. C'est à dire

Request.Headers.Add("Accept", "text/json");
return Request.CreateResponse(HttpStatusCode.OK, yourobject);

ou

Request.Headers.Add("Accept", "application/xml");
return new Rss20FeedFormatter(feed);
6
Eric Herlitz

Si votre demande spécifie le type MIME, par exemple application/json, puis l'API Web formatera la réponse de manière appropriée.

Si vous essayez de déboguer votre API Web manuellement, utilisez un outil comme Fiddler 2 pour spécifier le type.

Cet article décrit le concept.

5
Jim Yarbro

Bien que la réponse acceptée par vijayjan15 semble la meilleure façon de procéder pour votre situation spécifique (c'est-à-dire, en utilisant MediaTypeMappings), vous pouvez également avoir deux méthodes différentes, une qui renvoie XML et une qui retourne JSON. Pour ce faire, vous pouvez instancier une HttpConfiguration spécifique au contrôleur (pour éviter de modifier celle dans GlobalConfiguration.Configuration):

public MyReturnType GetMyTypeAsXml() {
    Configuration = new HttpConfiguration();
    Configuration.Formatters.Clear();
    Configuration.Formatters.Add(new XmlMediaTypeFormatter());

    return new MyReturnType();
}

public MyReturnType GetMyTypeAsJson() {
    Configuration = new HttpConfiguration();
    Configuration.Formatters.Clear();
    Configuration.Formatters.Add(new JsonMediaTypeFormatter());

    return new MyReturnType();
}

Je ne sais pas combien de temps il y a pour faire tourner une nouvelle instance de HttpConfiguration (je soupçonne pas beaucoup), mais la nouvelle instance est livrée avec la collection Formatters remplie par défaut, c'est pourquoi vous devez l'effacer juste après l'instanciation il. Notez que si vous n'utilisez pas Configuration = new HttpConfiguration () et modifiez directement la configuration, il modifie la propriété GlobalConfiguration.Configuration (donc, cela aurait un impact sur toutes vos autres méthodes WebApi - mauvais!).

3
Kirkaiya

QueryStringMapping` est une bonne solution mais j'ai besoin d'une valeur par défaut pour le type.

pour xml: localhost:49533/api/?type=xml

pour json: localhost:49533/api/

Je résous cette situation comme ça:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
var jSettings = new JsonSerializerSettings();

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", new MediaTypeHeaderValue("application/xml")));
2
Paradox