Не найден подходящий конструктор для фильтра типов - PullRequest
0 голосов
/ 18 октября 2018

У меня есть этот typefilter, который был недавно создан, и он расположен в отдельном проекте.

public class RolesFilterAttribute : TypeFilterAttribute
{
    public RolesFilterAttribute() : base(typeof(RolesFilterAttributeImpl))
    {

    }

    public class RolesFilterAttributeImpl : IActionFilter
    {
        private readonly ValidateRoleClient validateRoleClient;
        private string Role;
        private string SecretKey;
        public RolesFilterAttributeImpl(string Role, string SecretKey, ValidateRoleClient validateRoleClient)
        {
            this.validateRoleClient = validateRoleClient;
            this.Role = Role;
            this.SecretKey = SecretKey;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.HttpContext.Request.Cookies["Token"] != null || context.HttpContext.Request.Cookies["RefreshToken"] != null)
            {
                TokenViewModel tvm = new TokenViewModel
                {
                    Token = context.HttpContext.Request.Cookies["Token"],
                    RefreshToken = context.HttpContext.Request.Cookies["RefreshToken"]
                };
                ValidateRoleViewModel vrvm = new ValidateRoleViewModel
                {
                    Role = Role,
                    SecretKey = SecretKey,
                    Token = tvm
                };
                validateRoleClient.ValidateRole(vrvm);
            }
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            throw new NotImplementedException();
        }
    }
}

Вот как я объявляю это выше моего метода:

[TypeFilter(typeof(RolesFilterAttribute), Arguments = new object[] { "role", "abc1234" })]
public IActionResult About()
{
    return View();
}

Я считаю, что я объявил то, что мне нужно, в моем Startup.cs

services.AddScoped<ValidateRoleClient>();
services.AddScoped<RolesFilterAttribute>();

Однако, когда я запускаю приложение и перехожу на страницу about, я сталкиваюсь со следующим:

Произошло необработанное исключение при обработке запроса.InvalidOperationException: не удалось найти подходящий конструктор для типа 'App.Link.Filters.RolesFilterAttribute'.Убедитесь, что тип конкретный, а службы зарегистрированы для всех параметров публичного конструктора.Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor (Тип instanceType, Type [] argumentsTypes, вне ConstructorInfo MatchConstructor, вне Nullable [] parameterMap)

Что еще мне не хватает, что я не объявляю?

1 Ответ

0 голосов
/ 18 октября 2018
[TypeFilter(typeof(RolesFilterAttribute), …]

Это говорит о том, что тип фильтра, который вы хотите создать - RolesFilterAttribute.В фильтре типов вы также передаете два аргумента "role" и "abc1234".Поэтому, когда фильтр типов инициирует создание RolesFilterAttribute, он будет искать конструктор, который принимает эти две строки.Но есть только один конструктор:

public RolesFilterAttribute()
    : base(typeof(RolesFilterAttributeImpl))
{ }

Таким образом, у вас есть два параметра для конструктора без параметров.Вот почему вы получаете сообщение об ошибке.

Вместо этого вам нужно, чтобы атрибут [TypeFilter] создал реальный фильтр.Таким образом, вам нужно передать тип RolesFilterAttributeImpl:

[TypeFilter(typeof(RolesFilterAttributeImpl), Arguments = new object[] { "role", "abc1234" })]

В этот момент ваш RolesFilterAttribute также станет избыточным, так что вы можете просто избавиться от него и просто определить RolesFilterAttributeImpl (которыйЯ бы переименовал просто в RolesFilter, поскольку это фильтр, а не атрибут или реализация атрибута.

Кроме того, поскольку вы используете [TypeFilter], вам не необходимо зарегистрироватьсяваш тип фильтра с вашим контейнером внедрения зависимости.Вам нужно только зарегистрировать зависимости вашего типа, поэтому в вашем случае только ValidateRoleClient.

Таким образом, ваша реализация фильтра будет выглядеть так:

public class RolesFilter : IActionFilter
{
    private readonly ValidateRoleClient validateRoleClient;
    private readonly string role;
    private readonly string secretKey;

    public RolesFilter(string role, string secretKey, ValidateRoleClient validateRoleClient)
    {
        this.validateRoleClient = validateRoleClient;
        this.role = role;
        this.secretKey = secretKey;
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // …
    }

    public void OnActionExecuting(ActionExecutingContext context)
    { }
}

[TypeFilter] это кстати.только один способ разрешить указание фильтров с использованием атрибутов.Вы также можете создать свой собственный атрибут, который на самом деле является просто фабрикой фильтров , которая отвечает за создание экземпляра фильтра во время выполнения.Это то, что [TypeFilter] делает для вас по умолчанию.

См. Также мой связанный ответ на тему использования зависимостей в фильтрах MVC .

...