我正在使用 ASP.NET Web API 的 ApiController 将业务逻辑公开为 Web 服务。我正在测试 XML 和 JSON,因为我们对两者都有需求,而且我一直在使用 Fiddler 进行测试。我已将其缩小为:IList<T>
由于某种原因,拥有一个属性会强制使用 JSON,但将属性更改为List<T>
允许 JSON 或 XML。不幸的是,我需要这些来使用IList<T>
,那么我怎样才能从具有IList<T>
属性的对象中生成 XML 呢?
如果我使用以下 HTML 标头 GET http://localhost:4946/Api/MyBizLog/GetDomainObject?id=foo
:
Authorization: basic ***************
Accept: application/xml
Host: localhost:4946
如果抛出异常,我会返回 JSON。如果我更改Content-Type
为Content-Type: application/xml
,如果抛出异常,我会得到 XML。但是,如果没有抛出异常,我总是会得到 JSON。
我正在调用的方法有一个签名,如public virtual MyDomainObject GetDomainObject(String id)
.
如何让它返回我在成功和失败时要求的内容类型?
我有以下 WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "AlternativeApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { }
);
config.Formatters.XmlFormatter.UseXmlSerializer = true;
}
}
更多信息
我根据@Darren Miller 的建议安装了 WebAPI 跟踪,得到以下信息:
我在动作的第一行设置了一个断点。然后我从 Fiddler 发送了 GET。当执行在断点处停止时,输出显示如下:
iisexpress.exe Information: 0 : Request, Method=GET, Url=http://localhost:4946/Api/MyBizLog/GetDomainObject?id=foo, Message='http://localhost:4946/Api/MyBizLog/GetDomainObject?id=foo'
iisexpress.exe Information: 0 : Message='MyBizLog', Operation=DefaultHttpControllerSelector.SelectController
iisexpress.exe Information: 0 : Message='WebApp.Api.MyBizLogController', Operation=DefaultHttpControllerActivator.Create
iisexpress.exe Information: 0 : Message='WebApp.Api.MyBizLogController', Operation=HttpControllerDescriptor.CreateController
iisexpress.exe Information: 0 : Message='Selected action 'GetDomainObject(String id)'', Operation=ApiControllerActionSelector.SelectAction
iisexpress.exe Information: 0 : Message='Parameter 'id' bound to the value 'foo'', Operation=ModelBinderParameterBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Message='Model state is valid. Values: id=foo', Operation=HttpActionBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Operation=TransactionalApiFilterAttribute.ActionExecuting
然后我让执行继续,我得到了以下信息:
iisexpress.exe Information: 0 : Message='Action returned 'DomainObjects.MyDomainObject'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync
iisexpress.exe Information: 0 : Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
iisexpress.exe Information: 0 : Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
iisexpress.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=TransactionalApiFilterAttribute.ActionExecuted, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=MyBizLogController.ExecuteAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Response, Status=200 (OK), Method=GET, Url=http://localhost:4946/Api/MyBizLog/GetDomainObject?id=foo, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
iisexpress.exe Information: 0 : Operation=JsonMediaTypeFormatter.WriteToStreamAsync
iisexpress.exe Information: 0 : Operation=MyBizLogController.Dispose
我确实有一个ActionFilterAttribute
读取基本身份验证并告诉业务逻辑层当前用户是谁,但跳过它不会改变结果。
还有更多信息
所以我把它缩小到IList和List。如果我#define WORKS
,我会得到 XML。如果我#define DOESNT_WORK
,我会得到 JSON。这实际上是实际运行的代码。
public class Bar
{
}
public class Foo
{
#if WORKS
public virtual List<Bar> Bars { get; set; }
#elif DOESNT_WORK
public virtual IList<Bar> Bars { get; set; }
#endif
}
[HttpPost]
[HttpGet]
public Foo Test()
{
return new Foo();
}