带有基于命名空间的 ApiController 的自定义 ApiExplorer

问题描述 投票:0回答:3

我正在尝试在我的后端系统中添加 API 文档。 默认 ApiExplorer 和帮助页面工作得非常好,直到我向我的 API 控制器引入版本为止。

为了添加版本,我在 Controllers 文件夹下创建了子文件夹:

  • v1
  • v2
  • v3

并且有基于版本的 API 控制器。为了让我的 API 可以被发现,我必须重写

DefaultHttpControllerSelector
以考虑任何客户端提供的命名空间并将它们映射到正确的控制器:

这破坏了我的默认 ApiExplorer,并且以下属性返回零 api 描述

Configuration.Services.GetApiExplorer().ApiDescriptions

我如何定制现有的 ApiExplorer 并帮助他找到我的 Api 控制器而不是重写整个 ApiExplorer 实现。我真的需要展示在哪里可以找到我的 API 控制器。

请指教。

asp.net-mvc documentation asp.net-apicontroller asp.net-mvc-apiexplorer
3个回答
8
投票

我将向您展示一种方法。这段代码仅供学习。这里我不谈论设计和最佳实践,所以请随意更改您想要的任何内容。

那么,您必须遵循以下步骤:

1)创建自定义 ApiExplorer:

public class MyApiExplorer: ApiExplorer
{
    private readonly string _version;

    public MyApiExplorer(string version) : base(GlobalConfiguration.Configuration)
    {
        _version = version != null ? version.ToUpperInvariant() : "V1";

        foreach(var apiDescription in ApiDescriptions)
        {
            apiDescription.RelativePath = apiDescription.RelativePath.Replace("{version}", _version);
        }

    }

    public override bool ShouldExploreController(string controllerVariableValue, HttpControllerDescriptor controllerDescriptor,
        IHttpRoute route)
    {
        return controllerDescriptor.ControllerType.FullName.Contains(_version);
    }

}

a) 在构造函数中 _version 将被转换为大写(就在 case 它将作为小写传递)但如果它为 null 那么它将 默认为V1。然后更改相对路径以显示特定版本 而不是{版本}。

b) ShouldExploreController(简而言之) 决定是否在文档中显示特定控制器。在 在这种情况下,我们将仅显示其类型全名包含的控制器 选择的版本。

2)转到HelpController类并更改Index方法,如下所示:

public ActionResult Index(string version)
{
    //...

    Configuration.Services.Replace(typeof(IApiExplorer), new MyApiExplorer(version));

    return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}

我们正在用我们自己的 ApiExplorer 替换当前的 ApiExplorer,以便 调用 Configuration.Services.GetApiExplorer() 时返回

现在您可以使用 .../help?version=v1 或 .../help?version=v2 或 .../help?version=v3,您将获得特定的 api 控制器文档。


6
投票

结果发现和ApiExplorer没有任何关系。相反,您应该修改基于名称空间的控制器选择器:

NamespaceHttpControllerSelector : DefaultHttpControllerSelector
{
//...
    public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() 
    {
        var mapping = base.GetControllerMapping();
        mapping["User"] = new HttpControllerDescriptor
        {
            Configuration = _httpConfig,
            ControllerName = "User",
            ControllerType = typeof(UserController)
        };
        //...
        return mapping;
    }
    //...  }

就是这样。之后,默认 ApiExplorer 将找到您的控制器并获取所有操作。


1
投票

我最近遇到了类似的问题,并用以下方法解决了我的问题: 2 地点:

public class VersionControllerSelector : IHttpControllerSelector

public class VersionControllerSelector : DefaultHttpControllerSelector

...还有...

public VersionControllerSelector(HttpConfiguration config)

public VersionControllerSelector(HttpConfiguration config) : base(config)
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.