ASP.NET WebAPI - Как сканировать зарегистрированные действия

У меня есть несколько методов в моем WebApi, которые возвращают HttpResponseMessage. Поскольку тип ответа неизвестен, я должен зарегистрировать их в HelpPageConfig, используя что-то вроде

config.SetActualResponseType(typeof(X), "SomeController", "GetX");

Я хотел бы зарегистрировать их, используя пользовательский атрибут [ActualResponse(typeof(X)] где контроллер объявлен, чтобы избежать создания большого объекта реестра, который ссылается на все в немного запутанном списке.

Как я могу запросить конфигурацию, чтобы получить список зарегистрированных контроллеров и действий и их атрибутов, чтобы я мог автоматически вызывать SetActualResponseType?

1 ответ

Решение

Я исследовал источники mvc и web api и не нашел места, где можно внедрить такую ​​логику. Поиск методов действия в mvc/web api - непростая задача, поскольку существует ряд проверок, которые определяют, является ли метод методом действия или обычным методом (на основе зарегистрированных маршрутов и т. Д.). В вашем случае вам нужно обрабатывать только методы с вашим пользовательским атрибутом ActualResponse, верно? Так что вы можете сделать это с отражением. Конечно, такие вещи не быстрые и приносят некоторый удар по производительности. Но если вы запускаете такую ​​логику один раз в Application_Start, я думаю, что это приемлемо.

Пример реализации:

public static class ActionMethodsRegistrator
{
    private static readonly Type ApiControllerType = typeof(IHttpController);

    public static void RegisterActionMethods(YourCustomConfig config)
    {
        // find all api controllers in executing assembly            
        var contollersTypes = Assembly.GetExecutingAssembly().GetTypes()
            .Where(foundType => ApiControllerType.IsAssignableFrom(foundType));

        // you may also search for controllers in all loaded assemblies e.g.
        // var contollersTypes = AppDomain.CurrentDomain.GetAssemblies()
        //    .SelectMany(s => s.GetTypes())
        //    .Where(foundType => ApiControllerType.IsAssignableFrom(foundType));                

        foreach (var contollerType in contollersTypes)
        {
            // you may add more restriction here for optimization, e. g. BindingFlags.DeclaredOnly
            // I took search parameters from mvc/web api sources.
            var allMethods = contollerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);

            foreach (var methodInfo in allMethods)
            {
                var actualResponseAttrubute = methodInfo.GetCustomAttribute<ActualResponseAttribute>();
                if (actualResponseAttrubute != null)
                {                       
                    config.SetActualResponseType(actualResponseAttrubute.Type, contollerType.Name, methodInfo.Name);                        
                }
            }
        }
    }
}

Файл Global.asax:

    protected void Application_Start()
    {
        //....
        YourCustomConfig config = InitializeConfig();
        ActionMethodsRegistrator.RegisterActionMethods(config);
    }
Другие вопросы по тегам