web-dev-qa-db-fra.com

Comment obtenir que l'API Web ASP.NET renvoie JSON au lieu de XML à l'aide de Chrome?

En utilisant le plus récent API Web ASP.NET, dans Chrome Je vois du XML - comment puis-je le changer pour demander JSON afin que je puisse le voir dans le navigateur? Je crois que cela fait simplement partie des en-têtes de demande, est-ce que je me trompe?

1220
naspinski

Je viens d'ajouter ce qui suit dans la classe App_Start / WebApiConfig.cs de mon projet d'API Web MVC.

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html") );

Cela garantit que vous obtenez JSON sur la plupart des requêtes, mais vous pouvez obtenir xml lorsque vous envoyez text/xml.

Si vous avez besoin de la réponse Content-Type comme application/json, veuillez vérifier réponse de Todd ci-dessous .

NameSpace utilise System.Net.Http.Headers;

1668
Felipe Leusin

Si vous faites cela dans la WebApiConfig, vous obtiendrez JSON par défaut, mais cela vous permettra quand même de renvoyer du XML si vous passez text/xml en tant que requête Accept en-tête.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
    }
}

Si vous n'utilisez pas le type de projet MVC et que vous ne disposiez donc pas de cette classe pour commencer, voir cette réponse pour plus de détails sur la manière de l'incorporer.

494
Glenn Slaven

J'aime approche de Felipe Leusin mieux - assurez-vous que les navigateurs utilisent JSON sans compromettre la négociation de contenu des clients qui souhaitent réellement utiliser XML. La seule chose qui me manquait était que les en-têtes de réponse contenaient toujours le type de contenu: text/html. Pourquoi était-ce un problème? Parce que j'utilise le extension JSON Chrome , qui inspecte le type de contenu, et je n'obtiens pas le joli formatage auquel je suis habitué. J'ai corrigé cela avec un formateur personnalisé qui accepte les requêtes text/html et renvoie les réponses application/json:

public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
    public BrowserJsonFormatter() {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        this.SerializerSettings.Formatting = Formatting.Indented;
    }

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/json");
    }
}

Inscrivez-vous comme ça:

config.Formatters.Add(new BrowserJsonFormatter());
300
Todd Menier

L'utilisation de RequestHeaderMapping fonctionne encore mieux, car elle définit également le Content-Type = application/json dans l'en-tête de la réponse, ce qui permet à Firefox (avec le complément JSONView) de formater la réponse au format JSON.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", 
                              "text/html",
                              StringComparison.InvariantCultureIgnoreCase,
                              true, 
                              "application/json"));
287
dmit77

Conseil n ° 3 de MVC4 - Suppression du formateur XML de l’API Web ASP.Net

Dans Global.asax ajoutez la ligne:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

ainsi:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    BundleTable.Bundles.RegisterTemplateBundles();
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
182
Yakir Manor

Dans le WebApiConfig.cs , ajoutez à la fin de la fonction Register :

// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);

Source .

109

Dans le Global.asax j'utilise le code ci-dessous. Mon URI pour obtenir JSON est http://www.digantakumar.com/api/values?json=true

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new  QueryStringMapping("json", "true", "application/json"));
}
91
Diganta Kumar

Examinez la négociation de contenu dans WebAPI. Ces ( Partie 1 & Partie 2 ) des articles de blog merveilleusement détaillés et détaillés expliquent comment cela fonctionne.

En bref, vous avez raison et il vous suffit de définir les en-têtes de demande Accept ou Content-Type. Étant donné que votre action n'est pas codée pour renvoyer un format spécifique, vous pouvez définir Accept: application/json.

53
Aaron Daniels

Comme la question est spécifique à Chrome, vous pouvez obtenir le extension Postman qui vous permet de définir le type de contenu de la demande.

Postman

43
Chris S

Une option rapide consiste à utiliser la spécialisation MediaTypeMapping. Voici un exemple d'utilisation de QueryStringMapping dans l'événement Application_Start:

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

Maintenant, chaque fois que l'URL contient la chaîne de requête? A = b dans ce cas, la réponse Json sera affichée dans le navigateur.

34
suhair

Ce code fait de json ma valeur par défaut et me permet d’utiliser également le format XML. Je vais simplement annexer le xml=true.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Merci tout le monde!

30
jayson.centeno

N'utilisez pas votre navigateur pour tester votre API.

Au lieu de cela, essayez d'utiliser un client HTTP qui vous permet de spécifier votre requête, telle que CURL ou même Fiddler.

Le problème avec ce problème est dans le client, pas dans l'API. L'API Web se comporte correctement, à la demande du navigateur.

20
dmyoko

La plupart des réponses ci-dessus sont parfaitement logiques. Puisque vous voyez les données formatées au format XML, cela signifie que le formateur XML est appliqué. Vous pouvez donc visualiser le format JSON en supprimant simplement XMLFormatter du paramètre HttpConfiguration, comme suit:

public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );                
            config.Formatters.Remove(config.Formatters.XmlFormatter);                
            config.EnableSystemDiagnosticsTracing();
        }

jSON étant le format par défaut

15
pavan kumar

J'ai utilisé un filtre d'action global pour supprimer Accept: application/xml lorsque l'en-tête User-Agent contient "Chrome":

internal class RemoveXmlForGoogleChromeFilter : IActionFilter
{
    public bool AllowMultiple
    {
        get { return false; }
    }

    public async Task<HttpResponseMessage> ExecuteActionFilterAsync(
        HttpActionContext actionContext,
        CancellationToken cancellationToken,
        Func<Task<HttpResponseMessage>> continuation)
    {
        var userAgent = actionContext.Request.Headers.UserAgent.ToString();
        if (userAgent.Contains("Chrome"))
        {
            var acceptHeaders = actionContext.Request.Headers.Accept;
            var header =
                acceptHeaders.SingleOrDefault(
                    x => x.MediaType.Contains("application/xml"));
            acceptHeaders.Remove(header);
        }

        return await continuation();
    }
}

Semble travailler.

10
Roger Lipscombe

J'ai trouvé le Chrome app "Avancé REST Client" parfaitement adapté aux services REST. Vous pouvez définir le type de contenu sur application/json, entre autres: client avancé REST client

9
Mike Rowley

Le formatage correct est renvoyé par le formateur de type de support. Comme d'autres l'ont mentionné, vous pouvez le faire dans la classe WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        // Configure Web API to return JSON
        config.Formatters.JsonFormatter
        .SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));

        ...
    }
}

Pour plus, vérifiez:

Si vos actions renvoient du code XML (ce qui est le cas par défaut) et que vous n’avez besoin que d’une méthode spécifique pour renvoyer JSON, vous pouvez alors utiliser un ActionFilterAttribute et l’appliquer à cette action spécifique.

Attribut de filtre:

public class JsonOutputAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
        var value = content.Value;
        Type targetType = actionExecutedContext.Response.Content.GetType().GetGenericArguments()[0];

        var httpResponseMsg = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            RequestMessage = actionExecutedContext.Request,
            Content = new ObjectContent(targetType, value, new JsonMediaTypeFormatter(), (string)null)
        };

        actionExecutedContext.Response = httpResponseMsg;
        base.OnActionExecuted(actionExecutedContext);
    }
}

Application à l'action:

[JsonOutput]
public IEnumerable<Person> GetPersons()
{
    return _repository.AllPersons(); // the returned output will be in JSON
}

Notez que vous pouvez omettre le mot Attribute dans la décoration d'action et utiliser simplement [JsonOutput] au lieu de [JsonOutputAttribute].

7
Stacked

Je ne comprends pas pourquoi la réponse est complexe. Bien sûr, il existe de nombreuses façons de le faire, avec QueryStrings, en-têtes et options ... mais ce que je crois être la meilleure pratique est simple. Vous demandez une URL simple (ex: http://yourstartup.com/api/cars) et vous obtenez en retour JSON. Vous obtenez JSON avec l'en-tête de réponse approprié:

Content-Type: application/json

En cherchant une réponse à cette même question, j'ai trouvé ce fil et je devais continuer parce que cette réponse acceptée ne fonctionnait pas exactement. J'ai trouvé une réponse que je trouve trop simple pour ne pas être la meilleure:

Définir le formateur WebAPI par défaut

Je vais ajouter mon conseil ici aussi.

WebApiConfig.cs

namespace com.yourstartup
{
  using ...;
  using System.Net.Http.Formatting;
  ...
  config.Formatters.Clear(); //because there are defaults of XML..
  config.Formatters.Add(new JsonMediaTypeFormatter());
}

J'ai une question de savoir d'où viennent les défauts (du moins ceux que je vois). Sont-ils .NET par défaut, ou peut-être créés ailleurs (par quelqu'un d'autre sur mon projet). Anways, espérons que cela aide.

5
Nick

selon la dernière version de ASP.net WebApi 2,

sous WebApiConfig.cs, cela fonctionnera

config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
4
A.T.

Voici une solution similaire à jayson.centeno et à d'autres réponses, mais en utilisant l'extension intégrée de System.Net.Http.Formatting.

public static void Register(HttpConfiguration config)
{
    // add support for the 'format' query param
    // cref: http://blogs.msdn.com/b/hongyes/archive/2012/09/02/support-format-in-asp-net-web-api.aspx
    config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
    config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");

    // ... additional configuration
 }

La solution visait principalement à prendre en charge le format $ pour OData dans les premières versions de WebApi, mais elle s'appliquait également à la mise en œuvre non-OData et renvoyait l'en-tête Content-Type: application/json; charset=utf-8 dans la réponse.

Il vous permet de fixer &$format=json ou &$format=xml à la fin de votre uri lors du test avec un navigateur. Cela n'interfère pas avec les autres comportements attendus lors de l'utilisation d'un client non navigateur, dans lequel vous pouvez définir vos propres en-têtes.

4
mdisibio
        config.Formatters.Remove(config.Formatters.XmlFormatter);
3
Gaurav Dubey

Vous pouvez utiliser comme ci-dessous:

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
3
Akshay Kapoor

Ajoutez simplement ces deux lignes de code sur votre classe WebApiConfig

public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
          //add this two line 
          config.Formatters.Clear();
          config.Formatters.Add(new JsonMediaTypeFormatter());


          ............................
      }
}
2
Md. Sabbir Ahamed

Vous venez de changer le App_Start/WebApiConfig.cs comme ceci:

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();
        //Below formatter is used for returning the Json result.
        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
        //Default route
        config.Routes.MapHttpRoute(
           name: "ApiControllerOnly",
           routeTemplate: "api/{controller}"
       );
    }
2
vaheeds

De MSDNCréation d'une application à une seule page avec ASP.NET et AngularJS (environ 41 minutes).

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // ... possible routing etc.

        // Setup to return json and camelcase it!
        var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
        formatter.SerializerSettings.ContractResolver =
            new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
    }

Il devrait être à jour, je l'ai essayé et cela a fonctionné.

1
lko

Un certain temps s'est écoulé depuis que cette question a été posée (et sa réponse), mais une autre option consiste à remplacer l'en-tête Accept sur le serveur lors du traitement de la demande à l'aide d'un MessageHandler, comme indiqué ci-dessous:

public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
                HttpRequestMessage request,
                CancellationToken cancellationToken)
    {
        var someOtherCondition = false;
        var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
        if (someOtherCondition && accHeader.Contains("application/xml"))
        {
            request.Headers.Remove("Accept");
            request.Headers.Add("Accept", "application/json");
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

someOtherCondition peut être n'importe quoi, y compris le type de navigateur, etc. Cela s'applique aux cas conditionnels où nous ne voulons parfois que remplacer la négociation de contenu par défaut. Sinon, comme indiqué dans les autres réponses, vous supprimeriez simplement un formateur inutile de la configuration.

Vous aurez besoin de l'enregistrer bien sûr. Vous pouvez le faire globalement:

  public static void Register(HttpConfiguration config) {
      config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
  }

ou sur une route à la fois:

config.Routes.MapHttpRoute(
   name: "SpecialContentRoute",
   routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
   defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
   constraints: null,
   handler: new ForceableContentTypeDelegationHandler()
);

Et puisqu'il s'agit d'un gestionnaire de messages, il s'exécutera à la fois sur la requête et sur la réponse du pipeline, un peu comme un HttpModule. Vous pouvez donc facilement reconnaître le remplacement avec un en-tête personnalisé:

public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
                HttpRequestMessage request,
                CancellationToken cancellationToken)
    {
        var wasForced = false;
        var someOtherCondition = false;
        var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
        if (someOtherCondition && accHeader.Contains("application/xml"))
        {
            request.Headers.Remove("Accept");
            request.Headers.Add("Accept", "application/json");
            wasForced = true;
        }

        var response =  await base.SendAsync(request, cancellationToken);
        if (wasForced){
          response.Headers.Add("X-ForcedContent", "We overrode your content prefs, sorry");
        }
        return response;
    }
}
1
rism

Voici le moyen le plus simple que j'ai utilisé dans mes applications. Ajouter donné ci-dessous 3 lignes de code dans la fonction App_Start\\WebApiConfig.cs dans la fonction Register

    var formatters = GlobalConfiguration.Configuration.Formatters;

    formatters.Remove(formatters.XmlFormatter);

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

L'API Web Asp.net sérialise automatiquement votre objet renvoyé en JSON et, lorsque le application/json est ajouté dans l'en-tête, le navigateur ou le destinataire comprendra que vous renvoyez le résultat JSON.

1
Vikas Bansal

Après avoir utilisé la réponse de Felipe Leusin pendant des années, après une récente mise à jour des bibliothèques principales et de Json.Net, j’ai rencontré un System.MissingMethodException: SupportedMediaTypes. La solution dans mon cas, si cela est utile aux autres personnes rencontrant la même exception inattendue, consiste à installer System.Net.Http. NuGet le supprime apparemment dans certaines circonstances. Après une installation manuelle, le problème a été résolu.

0
Charles Burns

WebApiConfig est l'endroit où vous pouvez configurer si vous voulez générer en json ou xml. par défaut c'est xml. dans la fonction register, nous pouvons utiliser les formats HttpConfiguration Formatters pour formater la sortie. System.Net.Http.Headers => MediaTypeHeaderValue ("text/html") est requis pour obtenir la sortie au format json. enter image description here

0
rocky_pps