我正在尝试实现此post中提到的API密钥验证程序。我遇到了一个问题,我在中间件类中使用注入的服务进行验证返回:
InvalidOperationException:无法从根提供程序解析'FoosballKeepr.Services.Interfaces.ILeagueService',因为它需要作用域服务'FoosballKeepr.Data.FoosballKeeprContext'。
我相信我正在Startup.cs中正确注册我的dbContext,服务和存储库。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//MVC
services.AddMvc();
//Database
var connection = @"Server=localhost\SQLEXPRESS;Database=FoosballKeepr;Trusted_Connection=True;";
services.AddDbContext<FoosballKeeprContext>(options => options.UseSqlServer(connection));
//Services
services.AddTransient<IPlayerService, PlayerService>();
services.AddTransient<ILeagueService, LeagueService>();
//Repositories
services.AddTransient<IPlayerRepository, PlayerRepository>();
services.AddTransient<ILeagueRepository, LeagueRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware<ApiKeyValidatorMiddleware>();
app.UseMvc();
}
}
自定义中间件验证器:
public class ApiKeyValidatorMiddleware
{
private readonly RequestDelegate _next;
private ILeagueService _leagueService;
public ApiKeyValidatorMiddleware(RequestDelegate next, ILeagueService leagueService)
{
_next = next;
_leagueService = leagueService;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Headers.Keys.Contains("x-api-key"))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("API Key Missing.");
return;
}
else
{
int leagueId = _leagueService.ValidateApiKey(context.Request.Headers["x-api-key"]);
if (leagueId == 0)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid API Key");
return;
}
else
{
context.Items["LeagueId"] = leagueId;
}
}
await _next.Invoke(context);
}
}
服务
public class LeagueService : ILeagueService
{
private readonly ILeagueRepository _leagueRepository;
public LeagueService(ILeagueRepository leagueRepository)
{
_leagueRepository = leagueRepository;
}
public int ValidateApiKey(string apiKey)
{
return _leagueRepository.ValidateApiKey(apiKey);
}
}
存储库
public class LeagueRepository : ILeagueRepository
{
private readonly FoosballKeeprContext _context;
public LeagueRepository(FoosballKeeprContext context)
{
_context = context;
}
public int ValidateApiKey(string apiKey)
{
var query = from l in _context.League
where l.ApiKey == apiKey
select l.LeagueId;
return query.FirstOrDefault();
}
}
这是我第一次实现自定义中间件功能,所以我觉得我的问题没有在正确的上下文中正确设置,但没有任何东西突然出现。这对任何人来说都很熟悉吗?
答案 0 :(得分:5)
问题是中间件没有范围,因为:
因此,当您需要注入作用域服务时,可以在Invoke
操作中执行此操作(所谓的方法注入):
public async Task Invoke(HttpContext context, ILeagueService service)
{
//...
}