Как я могу исключить контроллер из ASP. NET Core 3 Attribute Routing - PullRequest
0 голосов
/ 20 апреля 2020

Я использую ASP. NET Core 3.1 для моего веб-API. У меня есть несколько контроллеров, использующих маршрутизацию на основе атрибутов, и все хорошо.

Мы хотим иметь возможность переключать один или несколько контроллеров с флагами функций в конфигурации приложения. В идеале, если флаг не установлен, соответствующий контроллер должен перестать существовать в глазах API. Я пытаюсь найти лучший (или любой) способ сделать это.

По-видимому, не существует встроенного способа настройки того, какие контроллеры сканируются при использовании атрибутной маршрутизации, и нет способа изменить коллекцию контроллеров или конечных точек, найденных при маршрутизации. Вот фрагмент кода Startup.cs, о котором идет речь:

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {            
        app.UseRouting();
        app.UseEndpoints(e =>
        {
            if (!this.FeatureEnabled)
            {
                // DO SOMETHING?
            }

            e.MapControllers();
        });
    }

Я понимаю, что, вероятно, могу переключиться на более ручную рукописную маршрутизацию и указать каждый контроллер, действие и параметр в классе Startup, но я бы хотел скорее отказаться от этого требования флага функции, чем go по этому грязному пути.

Есть ли способ выбрать, какие контроллеры используются в API при использовании маршрутизации на основе атрибутов?

Ответы [ 3 ]

1 голос
/ 21 апреля 2020

В качестве альтернативы, вы можете использовать один из фильтров в ASP. NET Core , чтобы сделать это более гибким и удобочитаемым.

И, что важно, контроллеры за переключателями функций все еще действительные контроллеры в вашем приложении. То есть, если вы хотите протестировать эти контроллеры с помощью ваших специальных запросов целей тестирования, вы все равно можете это сделать.

Вы можете применить фильтр либо к уровню контроллера, либо к уровню действия, чтобы любая функция переключала все действия в контроллере или одно действие в контроллере.

Вот пример, выполненный с использованием ActionFilterAttribute:

public class ToggledAttribute : ActionFilterAttribute
{
    // Can reuse the attribute for different controllers / actions
    // based on different configuration
    public ToggledAttribute(string configurationName = null)
    {
        ConfigurationName = configurationName;
    }

    public string ConfigurationName { get; }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var isTestRequest =
            context.HttpContext.Request.Headers["x-my-test-header"].Count > 0;

        if (isTestRequest)
        {
            return;
        }

        var configuration = (IConfiguration)context.HttpContext.RequestServices
            .GetService(typeof(IConfiguration));

        // Somehow read toggle from configuration
        var featureEnabled = ...

        if (!featureEnabled)
        {
            context.Result = new NotFoundResult();
        }
    }
}

Примените к своим контроллерам или действиям, где необходимо переключение:

[Route("[controller]")]
[Toggled]
public class MyToggledController : ControllerBase
{
    // OR
    [Toggled]
    [HttpGet]
    public int Get()
    {
        return 1;
    }
}
1 голос
/ 20 апреля 2020

Вы можете реализовать свой собственный ControllerFeatureProvider и решить, какие контроллеры вы хотите иметь в своем приложении.

public class CustomControllerFeatureProvider : ControllerFeatureProvider
{
    private readonly IConfiguration _configuration;

    public CustomControllerFeatureProvider(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    protected override bool IsController(TypeInfo typeInfo)
    {
        var isController = base.IsController(typeInfo);

        if (isController)
        {
            var enabledController = _configuration.GetValue<string[]>("EnabledController");

            isController = enabledController.Any(x => typeInfo.Name.Equals(x, StringComparison.InvariantCultureIgnoreCase));
        }

        return isController;
    }
}

И добавить его в startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .ConfigureApplicationPartManager(manager =>
        {
            manager.FeatureProviders.Add(new CustomControllerFeatureProvider(_configuration));
        });
}
0 голосов
/ 29 апреля 2020

Другие ответы являются возможными решениями, однако мы обнаружили гораздо более простое решение, использующее функцию флага функции, предоставленную Microsoft для ASP. NET Ядра, для которого требовалось всего несколько строк кода.

https://docs.microsoft.com/en-us/azure/azure-app-configuration/use-feature-flags-dotnet-core

Итак, наш стартап имеет следующую строку:

    public void ConfigureServices(IServiceCollection services)
    {
        // ...

        // By default this looks at the "FeatureManagement" config section
        services.AddFeatureManagement();
     }

А наш многофункциональный контроллер имеет новый атрибут вверху:

[ApiController]
[Route("api/v{version:apiVersion}/customers/{token}")]
// Feature.FooService is an enumeration we provide whose name is used as the feature flag
[FeatureGate(Feature.FooService)] 
public class FooController : ControllerBase
{
    ...
}

И наши настройки приложений. json имеет следующий раздел:

{
  "FeatureManagement": {
    "FooService" :  false
  }
}

Когда флаг отключен, весь контроллер возвращает 404 для любого действия, и он прекрасно работает, когда флаг установлен enabled.

При таком подходе есть две нерешенные незначительные проблемы:

  • Контроллер все еще отображается в нашей документации Swagger и Swagger UI. Я не знаю, возможно ли обойти это.
  • Контроллер все еще создается / создается, когда к нему делается запрос, даже если флаг функции отключен и действия возвращают 404. Это значит, что наша система Io C (Autofa * 1032) *) создавал весь граф объектов, необходимый для контроллера, хотя он не был действительно необходимым. Там также нет простого способа обойти это.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...