Asp.net mvc 带有基于名称空间的APIController的自定义ApiExplorer

Asp.net mvc 带有基于名称空间的APIController的自定义ApiExplorer,asp.net-mvc,api,documentation,asp.net-apicontroller,asp.net-mvc-apiexplorer,Asp.net Mvc,Api,Documentation,Asp.net Apicontroller,Asp.net Mvc Apiexplorer,我正在尝试在后端系统中添加API文档。 默认的ApiExplorer和帮助页面工作得非常好,直到我将版本引入Api控制器的那一刻 为了添加版本,我在控制器文件夹下创建了子文件夹: v1 v2 v3 并且有基于版本的Api控制器。为了使我的Api可被发现,我必须重写DefaultHttpControllerSelector,以考虑任何客户端提供的名称空间,并将它们映射到正确的控制器: 这破坏了我的默认ApiExplorer,以下属性返回零api描述 Configuration.Serv

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

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

  • v1
  • v2
  • v3
并且有基于版本的Api控制器。为了使我的Api可被发现,我必须重写DefaultHttpControllerSelector,以考虑任何客户端提供的名称空间,并将它们映射到正确的控制器:

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

Configuration.Services.GetApiExplorer().ApiDescriptions
我如何定制现有的ApiExplorer并帮助他找到我的Api控制器,而不是重写整个ApiExplorer实现。我真的需要显示在哪里可以找到我的Api控制器


请告知。

结果证明与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;
    }
    //...  }
NamespaceHttpControllerSelector:DefaultHttpControllerSelector
{
//...
公共覆盖IDictionary GetControllerMapping()
{
var-mapping=base.GetControllerMapping();
映射[“用户”]=新的HttpControllerDescriptor
{
配置=\u httpConfig,
ControllerName=“用户”,
ControllerType=typeof(用户控制器)
};
//...
回归映射;
}
//...  }

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

我最近遇到了一个类似的问题,并通过以下方法解决了我的问题: 2 LOC:

……还有

public VersionControllerSelector(HttpConfiguration config)


我会告诉你一个方法。此代码仅用于学习。这里我不是在谈论设计和最佳实践,所以请随意更改您想要的任何内容

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

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);
    }
public ActionResult Index(string version)
{
    //...

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

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

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

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

2)转到HelpController类并更改如下索引方法:

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);
    }
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控制器文档。

我正在尝试做完全相同的事情。。。你有没有可能想出如何实现这一点?我在下面回答了你的问题谢谢!我要试试这个解决方案。谢谢你的指导!将Configuration.Services.Replace放在HelpController的静态ctor中不是更好吗?否则,每次都会调用此函数。
public ActionResult Index(string version)
{
    //...

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

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