【问题标题】:injectiong an instance of ApplicationModel into an MVC service which will itself be a singleton将 ApplicationModel 的一个实例注入到 MVC 服务中,该服务本身就是一个单例
【发布时间】:2017-07-13 06:16:43
【问题描述】:

我希望仅当主体有权访问这些组件时才显示导航树的组件(无论是基于角色还是基于策略)。

我对 MVC 核心不是特别熟悉,但迄今为止的阅读表明我可以构建一个列表,列出哪些授权过滤器将应用于某个操作,例如:

    public NavigationNodePermissionResolver(ApplicationModel appModel)
    {
        foreach (var controllerModel in appModel.Controllers)
        {
            var contextFilters = controllerModel.Filters.OfType<IAsyncAuthorizationFilter>().ToList();
            foreach (ActionModel action in controllerModel.Actions)//todo restrain to HttpGet
            {
                var actionFilters = action.Filters.OfType<IAsyncAuthorizationFilter>().ToList();
            }
        }

如何将应用程序模型的实例注入 NavigationNodePermissionResolver 的实例化器中?

NavigationNodePermissionResolver 本身可以注入为:

services.TryAddSingleton<INavigationNodePermissionResolver, NavigationNodePermissionResolver>();

编辑

这个问题的后续 - 当我有一个 IAsyncAuthorizationFilters 列表时该怎么办是in this so question

作为后续信息,ApplicationModel 是我在this SO answer 中发现的 ApplicationModelProviderContext 的一个属性 - 它似乎大致是我所追求的,但它可能是我用来获取然后执行的方法授权过滤器完全错误

【问题讨论】:

    标签: asp.net-core-mvc


    【解决方案1】:

    我发现我可以实例化和注入实现 2 个接口的同一个实例。我最终进入了 Startup.ConfigureServices:

    var customAppModelProvider = new CustomApplicationModelProvider();
    services.AddSingleton<IApplicationModelProvider>(customAppModelProvider);
    services.AddSingleton<IActionFilterMap>(customAppModelProvider);
    

    以及实现:

    public interface IActionFilterMap
    {
        IEnumerable<IAsyncAuthorizationFilter> GetFilters(string area, string controller, string action);
    }
    public class CustomApplicationModelProvider : IApplicationModelProvider, IActionFilterMap
    {
        //It will be executed after AuthorizationApplicationModelProvider, which has order -990
        public int Order => 0;
    
        private ReadOnlyDictionary<ActionKey, IEnumerable<IAsyncAuthorizationFilter>> _authDictionary;
    
        public IEnumerable<IAsyncAuthorizationFilter> GetFilters(string area, string controller, string action)
        {
            var key = new ActionKey(area, controller, action);
            if (_authDictionary.TryGetValue(key, out IEnumerable<IAsyncAuthorizationFilter> returnVar))
            {
                return returnVar;
            }
            return null;//returning null rather than Enumerable.Empty so consuming method can detect if action found and has no Authorization, or action not found
    
        }
    
        public void OnProvidersExecuted(ApplicationModelProviderContext context)
        {
            var returnVar = new Dictionary<ActionKey, IEnumerable<IAsyncAuthorizationFilter>>();
            foreach (var controllerModel in context.Result.Controllers)
            {
                var controllerFilters = controllerModel.Filters.OfType<IAsyncAuthorizationFilter>().ToList();
                string area = controllerModel.Attributes.OfType<AreaAttribute>().FirstOrDefault()?.RouteValue;
                foreach (ActionModel action in controllerModel.Actions)//todo restrain to get
                {
                    var method = action.Attributes.OfType<HttpMethodAttribute>().FirstOrDefault();
                    if (method == null || method.HttpMethods.Contains("GET"))
                    {
                        var key = new ActionKey(area, controllerModel.ControllerName, action.ActionName);
                        if (action.Filters.OfType<AllowAnonymousFilter>().Any())
                        {
                            returnVar.Add(key, Enumerable.Empty<IAsyncAuthorizationFilter>());
                        }
                        else
                        {
                            var filters = controllerFilters.Concat(action.Filters.OfType<IAsyncAuthorizationFilter>()).ToArray();
                            returnVar.Add(key, filters);
                        }
                    }
                }
                _authDictionary = new ReadOnlyDictionary<ActionKey, IEnumerable<IAsyncAuthorizationFilter>>(returnVar);
            }
        }
    
        public void OnProvidersExecuting(ApplicationModelProviderContext context)
        {
            //empty
        }
    
        private class ActionKey : Tuple<string, string, string>
        {
            public ActionKey(string area, string controller, string action) : base(area ?? string.Empty, controller, action)
            {
                _hashCode = base.GetHashCode();
            }
    
            int _hashCode;
            public override int GetHashCode()
            {
                return _hashCode;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-22
      • 2017-07-05
      • 2017-07-23
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 2013-12-22
      相关资源
      最近更新 更多