How to force ASP.NET Web API to return JSON or XML

2020-02-02 04:40发布

问题:

I try to get the output XML or JSON data based on my input. I used the below WEB API code but not able to exact output.

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";
}

回答1:

Add the below code app_start event in global.asax file. In API Url add the query string:

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")));

e.g.:

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

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


回答2:

What you are trying to do will not work in a multi-threaded environment. You cannot add to and remove from the formatters collection on a per-request basis. Here is a better way of accomplishing what you want.

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


回答3:

Looked into this a bit more, and found your answer in another post:

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);
}


回答4:

It also works to force the accept headers. Great option if you aren't always returning HttpResponseMessage's. I.e

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

or

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


回答5:

If your request specifies the mime type, for example application/json, then web api will format the response appropriately.

If you are attempting to debug your web api manually, use a tool like Fiddler 2 to specify the type.

This article describes the concept.



回答6:

While the accepted answer by vijayjan15 seems the best way to go for your specific situation (that is, using the MediaTypeMappings), you could alternatively have two different methods, one that returns XML and one that returns JSON. To do that, you can instantiate a controller-specific HttpConfiguration (to avoid modifying the one in 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();
}

I'm not sure how much overhead there is in spinning up a new instance of HttpConfiguration (I suspect not a lot), but the new instance comes with the Formatters collection filled by default, which is why you have to clear it right after instantiating it. Note that it if you don't use Configuration = new HttpConfiguration(), and instead modify Configuration directly, it modifies the GlobalConfiguration.Configuration property (so, it would impact all your other WebApi methods - bad!).



回答7:

QueryStringMapping` is nice solution but I need a default value for type.

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

for json: localhost:49533/api/

I solve that situation like that:

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")));