C# 忽略ASP.NET Web API中的控制器

C# 忽略ASP.NET Web API中的控制器,c#,asp.net,asp.net-web-api,asp.net-routing,C#,Asp.net,Asp.net Web Api,Asp.net Routing,我们的团队维护一个自托管的ASP.NET Web API。该项目使用属性路由,我们有几十个现有的控制器。比方说,API是通过主路径/API/purpose1/…公开的,所有现有的控制器都作为资源放在下面 现在我想介绍一个新的并行主路径,e。g/api/purpose2/。应该可以通过配置文件中的布尔变量独立地激活两个主路径 由于所有控制器都在一个程序集中,因此属性路由方法始终查找并将它们添加到purpose1和purpose2。这与purpose1和purpose2的独立性相矛盾。因此,我对pu

我们的团队维护一个自托管的ASP.NET Web API。该项目使用属性路由,我们有几十个现有的控制器。比方说,API是通过主路径
/API/purpose1/…
公开的,所有现有的控制器都作为资源放在下面

现在我想介绍一个新的并行主路径,e。g<代码>/api/purpose2/。应该可以通过配置文件中的布尔变量独立地激活两个主路径

由于所有控制器都在一个程序集中,因此属性路由方法始终查找并将它们添加到
purpose1
purpose2
。这与
purpose1
purpose2
的独立性相矛盾。因此,我对
purpose1
使用属性路由,对
purpose2
使用基于约定的路由。这至少起了作用,但我对混合使用两种不同的路由方法不满意

因此,我的问题是:我可以使用属性路由禁用某些控制器类吗?

OnActionExecuting示例: V1控制器 V2控制器 支持版本控制的基本控制器 OnActionExecuting示例: V1控制器 V2控制器 支持版本控制的基本控制器 很好,但是它依赖于
System.Web.Mvc
。在我们的例子中,这个依赖性以前不存在,我找到了一个不需要添加它的解决方案

我扩展了以下方式:

内部类CustomHttpActionInvoker:ApiControllerActionInvoker
{
公共CustomHttpActionInvoker(IConfigProvider configProvider)
{
ConfigProvider=ConfigProvider;
InvokeActionFunc=base.InvokeActionAsync;
}
///仅适用于自动测试
内部CustomHttpActionInvoker(IConfigProvider配置提供程序,
Func invokeActionFunc)
{
ConfigProvider=ConfigProvider;
InvokeActionFunc=InvokeActionFunc;
}
专用IConfigProvider配置提供程序{get;}
私有函数InvokeActionFunc{get;}
/// 
公共覆盖任务InvokeActionAsync(HttpActionContext actionContext,CancellationToken CancellationToken)
{
var isRelevantRequest=actionContext.ControllerContext.Controller是MyRelevantController;
if(isRelevantRequest&ConfigProvider.IsPurpose1)
{
返回InvokeActionFunc(actionContext,cancellationToken);
}
if(!isRelevantRequest&&ConfigProvider.IsPurpose2)
{
返回InvokeActionFunc(actionContext,cancellationToken);
}
返回Task.FromResult(新的HttpResponseMessage(HttpStatusCode.NotFound));
}
}
引入了
内部
构造函数以支持更简单的单元测试

以下代码注册自定义类:

var config=new-HttpConfiguration();
config.maphttpAttribute路由();
Replace(typeof(ihttpackioninvoker),新的CustomHttpActionInvoker(MyConfigProvider));
很好,但是它依赖于
System.Web.Mvc
。在我们的例子中,这个依赖性以前不存在,我找到了一个不需要添加它的解决方案

我扩展了以下方式:

内部类CustomHttpActionInvoker:ApiControllerActionInvoker
{
公共CustomHttpActionInvoker(IConfigProvider configProvider)
{
ConfigProvider=ConfigProvider;
InvokeActionFunc=base.InvokeActionAsync;
}
///仅适用于自动测试
内部CustomHttpActionInvoker(IConfigProvider配置提供程序,
Func invokeActionFunc)
{
ConfigProvider=ConfigProvider;
InvokeActionFunc=InvokeActionFunc;
}
专用IConfigProvider配置提供程序{get;}
私有函数InvokeActionFunc{get;}
/// 
公共覆盖任务InvokeActionAsync(HttpActionContext actionContext,CancellationToken CancellationToken)
{
var isRelevantRequest=actionContext.ControllerContext.Controller是MyRelevantController;
if(isRelevantRequest&ConfigProvider.IsPurpose1)
{
返回InvokeActionFunc(actionContext,cancellationToken);
}
if(!isRelevantRequest&&ConfigProvider.IsPurpose2)
{
返回InvokeActionFunc(actionContext,cancellationToken);
}
返回Task.FromResult(新的HttpResponseMessage(HttpStatusCode.NotFound));
}
}
引入了
内部
构造函数以支持更简单的单元测试

以下代码注册自定义类:

var config=new-HttpConfiguration();
config.maphttpAttribute路由();
Replace(typeof(ihttpackioninvoker),新的CustomHttpActionInvoker(MyConfigProvider));

请检查和设置接口。实现这些功能可以让您完全控制控制器的创建。或者您可以重写控制器的方法来检查功能标志。@PeterCsala谢谢,我来看看这个。我必须实现这两个接口吗?IControllerFactory应该足够了。我将提供一个示例。您使用的是哪个.net核心或.net framework版本?请检查和查看接口。实现这些功能可以让您完全控制控制器的创建。或者您可以重写控制器的方法来检查功能标志。@PeterCsala谢谢,我来看看这个。我必须实现这两个接口吗?IControllerFactory应该足够了。我将提供一个示例。您使用的是哪个.net核心或.net框架版本?看起来不错,我将尝试这个。然而,我很好奇,
IControllerActivator
IControllerFactory
的示例看起来如何,请检查这两篇文章以获得更好的洞察力:,看起来不错,我将尝试这个。然而,我很好奇
IControllerActivator
IControllerFactory
的一个例子会是什么样子
[Route("api/[controller]")]
[ApiController]
public class SampleV1Controller : VersioningAwareControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return new OkObjectResult("V1");
    }
}
[Route("api/[controller]")]
[ApiController]
public class SampleV2Controller : VersioningAwareControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return new OkObjectResult("V2");
    }
}
public abstract class VersioningAwareControllerBase: ControllerBase, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        if (!FeatureFlags.ShouldDeprecateV1 ||
            !string.Equals(context.RouteData.Values["controller"].ToString(), "samplev1",
                StringComparison.OrdinalIgnoreCase))
            return;

        context.Result = NotFound();
        context.Canceled = true;
    }

    public void OnActionExecuting(ActionExecutingContext context) { }
}