当前位置: 首页 > 知识库问答 >
问题:

将服务注入操作过滤器

孙泉
2023-03-14

我试图将一个服务注入到我的操作过滤器中,但我没有在构造函数中注入所需的服务。以下是我所拥有的:

public class EnsureUserLoggedIn : ActionFilterAttribute
{
    private readonly ISessionService _sessionService;

    public EnsureUserLoggedIn()
    {
        // I was unable able to remove the default ctor 
        // because of compilation error while using the 
        // attribute in my controller
    }

    public EnsureUserLoggedIn(ISessionService sessionService)
    {
        _sessionService = sessionService;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Problem: _sessionService is null here
        if (_sessionService.LoggedInUser == null)
        {
            context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            context.Result = new JsonResult("Unauthorized");
        }
    }
}

我正在装饰我的控制器,就像这样:

[Route("api/issues"), EnsureUserLoggedIn]
public class IssueController : Controller
{
}

Startup.cs

services.AddScoped<ISessionService, SessionService>();

共有3个答案

薛飞星
2023-03-14

还有一个解决这个问题的方法。您可以通过上下文获取服务,如下代码所示:

public override void OnActionExecuting(ActionExecutingContext context)
{
    _sessionService = context.HttpContext.RequestServices.GetService<ISessionService>();
    if (_sessionService.LoggedInUser == null)
    {
        context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        context.Result = new JsonResult("Unauthorized");
    }
}

请注意,您必须在Startup.cs注册此服务

services.AddTransient<ISessionService, SessionService>();
潘学民
2023-03-14

您需要实现IFilterFactory

public class AuthorizationFilterFactory : IFilterFactory
{
    public bool IsReusable => false;

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        // manually find and inject necessary dependencies.
        var context = (IMyContext)serviceProvider.GetService(typeof(IMyContext));
        return new AuthorizationFilter(context);
    }
}

启动类中,注册过滤器工厂,而不是注册实际的过滤器:

services.AddMvc(options =>
{
    options.Filters.Add(new AuthorizationFilterFactory());
});
韶和璧
2023-03-14

参考以下文章:

ASP. NET核心操作过滤器

ASP中的操作筛选器、服务筛选器和类型筛选器。NET5和MVC6

将过滤器用作ServiceFilter

由于过滤器将用作服务类型,因此需要向框架IoC注册。如果直接使用动作过滤器,则不需要这样做。

Startup.cs

public void ConfigureServices(IServiceCollection services) {
    services.AddMvc();

    services.AddScoped<ISessionService, SessionService>();
    services.AddScoped<EnsureUserLoggedIn>();

    ...
}

使用ServiceFilter属性将自定义过滤器添加到MVC控制器方法和控制器类中,如下所示:

[ServiceFilter(typeof(EnsureUserLoggedIn))]
[Route("api/issues")]
public class IssueController : Controller {
    // GET: api/issues
    [HttpGet]
    [ServiceFilter(typeof(EnsureUserLoggedIn))]
    public IEnumerable<string> Get(){...}
}

还有其他的例子

>

将过滤器与基本控制器一起使用

按顺序使用过滤器

看看,给他们一个尝试,看看这是否解决了你的问题。

希望这有帮助。

 类似资料:
  • TakeLast 发射Observable发射的最后N项数据 使用TakeLast操作符修改原始Observable,你可以只发射Observable’发射的后N项数据,忽略前面的数据。 taskLast.n 使用takeLast操作符,你可以只发射原始Observable发射的后N项数据,忽略之前的数据。注意:这会延迟原始Observable发射的任何数据项,直到它全部完成。 takeLast的

  • Take 只发射前面的N项数据 使用Take操作符让你可以修改Observable的行为,只返回前面的N项数据,然后发射完成通知,忽略剩余的数据。 RxJava将这个操作符实现为take函数。 如果你对一个Observable使用take(n)(或它的同义词limit(n))操作符,而那个Observable发射的数据少于N项,那么take操作生成的Observable不会抛异常或发射onErro

  • SkipLast 抑制Observable发射的后N项数据 使用SkipLast操作符修改原始Observable,你可以忽略Observable’发射的后N项数据,只保留前面的数据。 使用SkipLast操作符,你可以忽略原始Observable发射的后N项数据,只保留之前的数据。注意:这个机制是这样实现的:延迟原始Observable发射的任何数据项,直到它发射了N项数据。 skipLast的

  • Skip 抑制Observable发射的前N项数据 使用Skip操作符,你可以忽略Observable’发射的前N项数据,只保留之后的数据。 RxJava中这个操作符叫skip。skip的这个变体默认不在任何特定的调度器上执行。 Javadoc: skip(int)) skip的这个变体接受一个时长而不是数量参数。它会丢弃原始Observable开始的那段时间发射的数据,时长和时间单位通过参数指定

  • Sample 定期发射Observable最近发射的数据项 Sample操作符定时查看一个Observable,然后发射自上次采样以来它最近发射的数据。 在某些实现中,有一个ThrottleFirst操作符的功能类似,但不是发射采样期间的最近的数据,而是发射在那段时间内的第一项数据。 RxJava将这个操作符实现为sample和throttleLast。 注意:如果自上次采样以来,原始Observ

  • Last 只发射最后一项(或者满足某个条件的最后一项)数据 如果你只对Observable发射的最后一项数据,或者满足某个条件的最后一项数据感兴趣,你可以使用Last操作符。 在某些实现中,Last没有实现为一个返回Observable的过滤操作符,而是实现为一个在当时就发射原始Observable指定数据项的阻塞函数。在这些实现中,如果你想要的是一个过滤操作符,最好使用TakeLast(1)。