【问题标题】:Need access to HttpContext from Razor filter method through constructor or other means需要通过构造函数或其他方式从 Razor 过滤方法访问 HttpContext
【发布时间】:2019-11-30 18:09:55
【问题描述】:

我已经阅读了所有其他关于这个问题的帖子,我确定这不是重复的。

我正在构建一个 Razor 页面过滤器以在我的 Startup.cs 类中使用,我需要访问 HttpContextI would normally do this through constructor injection using ASP.NET Core's DI capabilities. 我什至在 Startup.cs 中有通常的 services.AddHttpContextAccessor() 语句,并在我的项目的其他地方使用它。

由于我正在构建一个派生自 IAsyncPageFilter 并从 Startup.cs 类创建的 Razor page filter,因此它看起来好像我不能注入它(因为它是由启动创建的,而不是注入的)。

这里是添加过滤器到Startup.cs:

Startup.cs(截图)

    services.AddMvc(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
        options.Filters.Add(new RazorAsyncPageFilter(_logger, Configuration)); <---my filter
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

这是我的过滤器:

RazorAsyncPageFilter.cs

    public class RazorAsyncPageFilter : IAsyncPageFilter
    {
        private readonly ILogger _logger;
        private readonly IConfiguration _configuration;

        public string[] Scopes { get; set; }
        public string ScopeKeySection { get; set; }

        public RazorAsyncPageFilter(ILogger logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }
        public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
        {
            await Task.CompletedTask;
        }

        public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
        {
            VaultGraphServiceClient.OnMsalUiExceptionEvent += VaultGraphServiceClientOnOnMsalUiExceptionEvent;
            await next.Invoke();
        }
        
        private void VaultGraphServiceClientOnOnMsalUiExceptionEvent(object sender, MsalUiRequiredException e)
        {
            _logger.LogInformation($"Triggered authentication exception: {e.Message}");
            Scopes = new string[] { _configuration.GetValue<string>(ScopeKeySection) };
            var properties = BuildAuthenticationPropertiesForIncrementalConsent(Scopes, e, **I_NEED_CONTEXT_HERE**);
            new ChallengeResult(properties);
        }
    }

注意从另一个类中的事件处理程序触发的方法调用所需的上下文。我想将HttpContext 传递给过滤器类中的私有方法。

这是我尝试过的:

  1. Startup.cs 中为IHttpContextAccessor _httpContext 定义一个字段并将其传递给过滤器,但这显然不起作用,因为该上下文尚未建立。

  2. 从另一个方法传递上下文。这需要更多的工作,并且充满了warnings about passing it to a background thread

  3. 从我的调用 EventHandler 中注入上下文。不幸的是,这是从静态类调用的,据我所知,静态类中没有 DI 的概念。它是否正确?此外,我正在使用一个 EventHandler 委托来传递 MsalUiRequiredException 对象,并且只能传递一个对象。也许我可以为 event 类型使用不同的处理程序,但我对事件不够熟悉,无法理解如何做到这一点。

  4. 我正在考虑创建一个自定义类来保存 MsalUiRequiredExceptionHttpContext 可以在其中注入/传递到其他地方,但这似乎也有点矫枉过正,或者可能是上面 #2 的问题。

有什么建议吗?

【问题讨论】:

  • 我有一个想法,但不是答案。所以当我在 Asp.Net MVC 中做同样的事情时,我创建了一个新类并从 WebViewPage 抽象类继承。 F.e.: abstract class TViewPage&lt;TModel&gt; : System.Web.Mvc.WebViewPage&lt;TModel&gt; 您可以在 Asp.Net Core 中使用 RazorPage 类而不是 WebViewPage
  • 什么是VaultGraphServiceClient.OnMsalUiExceptionEvent
  • @Nkosi 它是对另一个静态类触发的事件的订阅。

标签: c# asp.net-core razor


【解决方案1】:

添加IHttpContextAccessor作为构造函数参数

public RazorAsyncPageFilter(ILogger logger, IConfiguration configuration, IHttpContextAccessor httpContext)
{
    _logger = logger;
    _configuration = configuration;
    _httpContext = httpContext;
}

并添加过滤器by type

options.Filters.Add<RazorAsyncPageFilter>()

【讨论】:

  • 有趣。那么按类型添加过滤器如何改变 DI 行为呢?看起来我可以只指定 ILogger、IConfiguration 和 IHttpContextAccessor 而无需传递它们。它们似乎在 RazorAsyncPageFilter 类中可用,而无需从 Startup.cs 传递它们。当我之前将它们添加到构造函数时,Startup.cs 类希望它们都传入。
  • @JasonShave-MSFT 可能我不明白你的问题,但它不会以任何方式改变 DI 行为,它只是使用它。在您的初始代码中,您自己实例化了过滤器,框架 DI 根本没有涉及
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 2017-12-15
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
相关资源
最近更新 更多