2013-11-14 32 views
37

我尝试根据输入获取输出的XML或JSON数据。我使用了下面的WEB API代码,但无法精确输出。如何强制ASP.NET Web API根据我的输入返回JSON或XML数据?

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

回答

73

global.asax文件中添加以下代码app_start事件。在API URL添加查询字符串:

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

例如为:

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

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

这里有个小技巧,如果你需要使用路由,而不是查询字符串,我通过继承创建一个自定义映射器从“MediaTypeMapping”并覆盖“TryMatchMediaType” –

+1

它不适用于路由'http:// localhost:49533/api/entity/1?type = xml ' – Marusyk

+0

它是否适用于HTTP路由,例如'[Route(“api/{type}/entity“)]'? – Lucas

9

你正在尝试做的事情在多线程环境下不起作用。您无法在每个请求的基础上添加或删除格式化程序集。这是完成你想要的更好的方法。

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

啊我看这类似于我找到了答案,漂亮 – jamiebarrow

5

如果您的请求指定的MIME类型,例如application/json,则Web API将相应地格式化响应。

如果您试图手动调试您的web api,请使用类似Fiddler 2这样的工具来指定类型。

This article描述了这个概念。

+0

+1我建议这样做,而不是在查询字符串上的自定义输入,因为它是执行此操作的标准方式 – jamiebarrow

+0

也许更好的链接是http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation – jamiebarrow

1

QueryStringMapping`是很好的解决方案,但我需要一个类型的默认值。

对XML:localhost:49533/api/?type=xml

为JSON:localhost:49533/api/

我解决这种情况像:

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

虽然通过vijayjan15接受的答案似乎去为您的具体情况最好的办法(也就是使用MediaTypeMappings),您可以选择使用两种不同的方法,一种返回XML,另一种返回JSON。要做到这一点,你可以实例化一个特定的控制器HttpConfiguration(避免修改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(); 
} 

我不知道有多少开销存在旋转起来HttpConfiguration的新实例(我怀疑不是很多),但新实例带有缺省填充的Formatters集合,这就是为什么您必须在实例化后立即清除它。请注意,如果不是,则使用Configuration = new HttpConfiguration(),而直接修改配置,它将修改GlobalConfiguration.Configuration属性(所以它会影响所有其他WebApi方法 - 不好!)。

+0

我想再次阅读jyarbro的答案;) – jamiebarrow

+1

我建议的另一个答案是基于假设问题作者本身无法访问请求(例如,修改头文件),或者想要在浏览器中发起请求时指定XML或JSON(在这种情况下,不同的浏览器发送不同的接受头文件,这样FireFox将显示XML,而IE将像JSON一样拉 - 如果他想成为显式的,他不能依赖头文件)。 ;-) – Kirkaiya

+0

是的,我假设他已经通过'id == 1'检查控制了请求,但是我想他只是在一个示例项目中试用它,所以说得很好:)我添加了一个答案,我想我在另一个SO帖子中找到了这样做的最佳方式。 – jamiebarrow

8

看着这有点多,发现你的答案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); 
} 
+0

现在* *实际上看起来很有用! – Kirkaiya

+0

@Kirkaiya我注意到Badri的回答后,他们似乎做了同样的事情,但这似乎使我更加感觉:)谢谢! – jamiebarrow

6

它也迫使接受头。伟大的选择,如果你不总是返回HttpResponseMessage's。一世。Ë

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

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

是否可以在控制器级别添加Request.Headers.Add片段 – aemorales1

相关问题