IFilterProvider und Trennung von Bedenken

Ich habe eine Situation, in der ich einige Abhängigkeiten in einen Aktionsfilter einfügen muss, nämlich meinen benutzerdefinierten Autorisierungsanbieter in mein benutzerdefiniertes Autorisierungsattribut. Ich bin auf viele Leute und Posts gestoßen, die sagten, wir sollten die 'Attribut-Metadaten' vom 'Verhalten' trennen. Dies ist sinnvoll und es gibt auch die Tatsache, dass Filterattribute nicht durch den 'DependencyResolver' instanziiert werden, so dass es schwierig ist, die Abhängigkeiten zu injizieren.

Also habe ich meinen Code ein wenig überarbeitet und wollte wissen, ob ich es richtig gemacht habe (ich verwende Castle Windsor als DI-Framework).

Zuerst habe ich mein Attribut entfernt, um nur die Rohdaten zu enthalten, die ich benötige

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : Attribute
{
    public string Code { get; set; }
}

Ich habe einen benutzerdefinierten Autorisierungsfilter erstellt, der die Logik zum Ermitteln der Berechtigung des aktuellen Benutzers enthält

public class MyAuthorizationFilter : IAuthorizationFilter
{
    private IAuthorizationProvider _authorizationProvider;
    private string _code;

    public MyAuthorizationFilter(IAuthorizationProvider authorizationProvider, string code)
    {
        Contract.Requires(authorizationProvider != null);
        Contract.Requires(!string.IsNullOrWhiteSpace(code));

        _authorizationProvider = authorizationProvider;
        _code = code;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            BaseController controller = filterContext.Controller as BaseController;
            if (controller != null)
            {
                if (!IsAuthorized(controller.CurrentUser, controller.GetCurrentSecurityContext()))
                {
                    // forbidden
                    filterContext.RequestContext.HttpContext.Response.StatusCode = 403;
                    if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
                    {
                        filterContext.Result = new RedirectToRouteResult("default", new RouteValueDictionary(new
                        {
                            action = "http403",
                            controller = "error"
                        }), false);
                    }
                    else
                    {
                        filterContext.Result = controller.InvokeHttp404(filterContext.HttpContext);
                    }
                }
            }
            else
            {

            }
        }
        else
        {
            filterContext.Result = new RedirectResult(FormsAuthentication.LoginUrl);
        }
    }

    private bool IsAuthorized(MyUser user, BaseSecurityContext securityContext)
    {
        bool has = false;
        if (_authorizationProvider != null && !string.IsNullOrWhiteSpace(_code))
        {
            if (user != null)
            {
                if (securityContext != null)
                {
                    has = _authorizationProvider.HasPermission(user, _code, securityContext);
                }
            }
        }
        else
        {
            has = true;
        }
        return has;
    }
}

Der letzte Teil bestand darin, einen benutzerdefinierten Filteranbieter zu erstellen, der dieses bestimmte Attribut abruft und meinen benutzerdefinierten Filter instanziiert, indem er seine Abhängigkeiten und alle benötigten Daten aus dem Attribut extrahiert.

public class MyAuthorizationFilterProvider : IFilterProvider
{
    private IWindsorContainer _container;

    public MyAuthorizationFilterProvider(IWindsorContainer container)
    {
        Contract.Requires(container != null);
        _container = container;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        Type controllerType = controllerContext.Controller.GetType();
        var authorizationProvider = _container.Resolve<IAuthorizationProvider>();
        foreach (MyAuthorizeAttribute attribute in controllerType.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
        {
            yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Controller, 0);
        }
        foreach (MyAuthorizeAttribute attribute in actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
        {
            yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Action, 0);
        }
    }
}

Der letzte Schritt ist das Registrieren des Filterproviders in der global.asax

FilterProviders.Providers.Add(new MyAuthorizationFilterProvider(_container));

Ich frage mich also erstens, ob ich die Idee richtig verstanden habe und zweitens, was verbessert werden könnte.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage