如何使用配置从库中注册 api 控制器

DaI*_*mTo 4 c# asp.net-core

我所做的是在类库中创建了一个小的 API。此 API 将被其他站点使用。将其视为我们所有网站都将包含的标准端点。

[Route("api/[controller]")]
[ApiController]
public class CustomController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }
}
Run Code Online (Sandbox Code Playgroud)

以上是在一个类库中。现在我想做的是能够以简单的方式将其添加到项目中。

app.UseCustomAPI("/api/crap");
Run Code Online (Sandbox Code Playgroud)

我不确定我应该如何处理到库中 api 控制器的路由。我创建了一个 CustomAPIMiddleware,它能够捕捉到我称之为“/api/crap”的东西,但是我不确定我应该如何将请求转发到库中的 CustomController

public async Task Invoke(HttpContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));
        PathString matched;
        PathString remaining;
        if (context.Request.Path.StartsWithSegments(_options.PathMatch, out matched, out remaining))
        {
            PathString path = context.Request.Path;
            PathString pathBase = context.Request.PathBase;
            context.Request.PathBase = pathBase.Add(matched);
            context.Request.Path = remaining;
            try
            {
                await this._options.Branch(context);
            }
            finally
            {
                context.Request.PathBase = pathBase;
                context.Request.Path = path;
            }
            path = new PathString();
            pathBase = new PathString();
        }
        else
            await this._next(context);
    }
Run Code Online (Sandbox Code Playgroud)

完成之后,我开始认为我可能以错误的方式处理了这个问题,实际上应该尝试以某种方式将其直接添加到路由表中。话虽如此,如果他们可以自定义自定义控制器从中读取的端点,我会喜欢它。

更新

以下确实有效。 从 ASP.NET 核心中的类库加载和注册 API 控制器

services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddApplicationPart(Assembly.Load(new AssemblyName("WebAPI"))); 
Run Code Online (Sandbox Code Playgroud)

然而,我真的在寻找一种中间类型的解决方案,以便用户可以简单地添加它,我可以配置默认设置,或者他们可以更改一些设置。上面的示例不允许更改设置。

 app.UseCustomAPI("/api/crap");
Run Code Online (Sandbox Code Playgroud)

从没有程序集的评论更新

如果我不添加 .AddApplicationPart(Assembly.Load(new AssemblyName("WebAPI")));

无法找到此本地主机页面未找到该网址的网页: https://localhost:44368/api/Custom

Kir*_*kin 5

为了在运行时自定义控制器的路由,您可以使用应用程序模型约定。在最简单的层面上,这可以通过自定义实现来实现IControllerModelConvention

public class CustomControllerConvention : IControllerModelConvention
{
    private readonly string newEndpoint;

    public CustomControllerConvention(string newEndpoint)
    {
        this.newEndpoint = newEndpoint;
    }

    public void Apply(ControllerModel controllerModel)
    {
        if (controllerModel.ControllerType.AsType() != typeof(CustomController))
            return;

        foreach (var selectorModel in controllerModel.Selectors)
            selectorModel.AttributeRouteModel.Template = newEndpoint;
    }
}
Run Code Online (Sandbox Code Playgroud)

此示例只是将现有模板 ( api/[controller])替换为SampleConvention构造函数中提供的任何内容。下一步是注册这个新约定,这可以通过调用AddMvc. 这是一个如何工作的示例:

services.AddMvc(o =>
{
    o.Conventions.Add(new CustomControllerConvention("api/whatever"));
});
Run Code Online (Sandbox Code Playgroud)

这就是让事情在这里工作所需的全部,但是当您从另一个程序集提供它时,我建议使用基于扩展方法的方法。这是一个例子:

public static class MvcBuilderExtensions
{
    public static IMvcBuilder SetCustomControllerRoute(this IMvcBuilder mvcBuilder, string newEndpoint)
    {
        return mvcBuilder.AddMvcOptions(o =>
        {
            o.Conventions.Add(new CustomControllerConvention(newEndpoint));
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

下面是一个示例:

services.AddMvc()
    .SetCustomControllerRoute("api/whatever");
Run Code Online (Sandbox Code Playgroud)

这整个方法意味着如果不调用SetCustomControllerRoute,api/Custom仍将用作默认值。