我目前正在使用Web API 2的属性路由(http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2)实现Web API。我还使用“帮助页面”模块,以便从XML注释(http://www.asp.net/web-api/overview/creating-web-apis/creating-api-help-pages)自动生成文档。
对于这个API,我提供了对可选返回格式扩展的支持,因此每个API方法都有一对定义的路由,如下所示:
[HttpGet]
[Route("Path/Foo")]
[Route("Path/Foo.{ext}")]
public HttpResponseMessage DoFoo()
{
// Some API function.
}
这允许用户点击其中任何一个并获得结果:
www.example.com/api/Controller/Path/Foo
www.example.com/api/Controller/Path/Foo.json
www.example.com/api/Controller/Path/Foo.xml
我的问题是,当帮助页面使用MapHttpAttributeRoutes()生成文档时,它会为每个方法选择两个路径。所以现在我看到了帮助:
api/Controller/Foo
api/Controller/Foo.{ext}
但我想只看到:
api/Controller/Foo.{ext}
我更希望在每个方法上隐藏非扩展路由,以便每个方法只显示一个帮助页面条目。
还有其他人尝试过类似的东西吗?是否有我失踪的工作?
答案 0 :(得分:9)
我的问题是,你的api的消费者会很容易理解{ext}
是可选的吗?...个人而言,我更喜欢默认行为......但无论如何以下是我的一些解决方法可以想到:
快速而肮脏的解决方法。将DoFoo拆分为2个动作,如DoFoo()和DoFooWithExt。请注意,我使用的是名为ApiExplorerSettings
的属性,用于HelpPage目的。示例如下:
[HttpGet]
[Route("Path/Foo")]
[ApiExplorerSettings(IgnoreApi=true)]
public HttpResponseMessage DoFoo()
{
return DoFooHelper();
}
[HttpGet]
[Route("Path/Foo.{ext}")]
public HttpResponseMessage DoFooWithExt()
{
return DoFooHelper();
}
private HttpResponseMessage DoFooHelper()
{
//do something
}
创建自定义ApiExplorer
(内部使用HelpPage功能)并检查以下特定路线,并决定是否显示该特定路线的操作。
// update the config with this custom implementation
config.Services.Replace(typeof(IApiExplorer), new CustomApiExplorer(config));
public class CustomApiExplorer : ApiExplorer
{
public CustomApiExplorer(HttpConfiguration config) : base(config)
{
}
public override bool ShouldExploreAction(string actionVariableValue, HttpActionDescriptor actionDescriptor, IHttpRoute route)
{
if (route.RouteTemplate.EndsWith("Path/Foo", StringComparison.OrdinalIgnoreCase))
{
return false;
}
return base.ShouldExploreAction(actionVariableValue, actionDescriptor, route);
}
}
从默认ApiDescription
获取所有ApiExplorer
的列表,然后过滤掉您不喜欢的说明。例:
Configuration.Services.GetApiExplorer().ApiDescriptions.Where((apiDesc) => !apiDesc.RelativePath.EndsWith("Path/Foo", StringComparison.OrdinalIgnoreCase))