我试图将一个服务注入到我的操作过滤器中,但我没有在构造函数中注入所需的服务。以下是我所拥有的:
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>();
还有一个解决这个问题的方法。您可以通过上下文获取服务,如下代码所示:
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>();
您需要实现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());
});
参考以下文章:
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)。