0

I have just added Middleware to my codes which giving this error when I wanted to run it

System.InvalidOperationException: 'Cannot resolve scoped service 'HORA_API.Model.AGUSContext' from root provider.'

program.cs

this is the program.cs

global using HORA_API.Model;
using HORA_API.Middleware;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<AGUSContext>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

 //app.UseAuthorization();
app.UseMiddleware<JwtMiddleware>();

app.MapControllers();

app.Run();

Appreciate any help on this. thank you

edited to add :

Full details of the exception

System.InvalidOperationException HResult=0x80131509 Message=Cannot resolve scoped service 'HORA_API.Model.AGUSContext' from root provider. Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass5_0.b__0(RequestDelegate next) at Microsoft.AspNetCore.Builder.ApplicationBuilder.Build() at Microsoft.AspNetCore.Builder.WebApplicationBuilder.b__27_0(RequestDelegate next) at Microsoft.AspNetCore.Builder.ApplicationBuilder.Build() at Microsoft.AspNetCore.Hosting.GenericWebHostService.d__37.MoveNext() at Microsoft.Extensions.Hosting.Internal.Host.d__12.MoveNext() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.d__4.MoveNext() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.d__4.MoveNext() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at Microsoft.AspNetCore.Builder.WebApplication.Run(String url) at Program.$(String[] args) in C:\Hora vs 090123\api\HORA-API\HORA-API\Program.cs:line 30

Middleware codes

 public async Task Invoke(HttpContext context, AGUSContext dataService)
{
    var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

    if (token != null)
        attachUserToContext(context, dataService, token);

    await _next(context);
}

private void attachUserToContext(HttpContext context, AGUSContext dataService, string token)
{
    try
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes("SecretToken");
        tokenHandler.ValidateToken(token, new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false,
            // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
            ClockSkew = TimeSpan.Zero
        }, out SecurityToken validatedToken);

        var jwtToken = (JwtSecurityToken)validatedToken;
        var email = jwtToken.Claims.First(x => x.Type == "id").Value;

        // attach user to context on successful jwt validation
        var useremail = dataService.Otps.FirstOrDefault(v => v.AlamatEmail == email);
        if (useremail != null)
        {
            context.Items["User"] = "Ok";
        }
    }
    catch
    {
        // do nothing if jwt validation fails
        // user is not attached to context so request won't have access to secure routes
    }

Attribute Authorization

    public void OnAuthorization(AuthorizationFilterContext context)
{
    if (context.HttpContext.Items["User"] == null)
    {
        // not logged in
        context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
    }
}

Then i added this on the controller

  private string generateJwtToken(string email)
    {
        // generate token that is valid for 7 days
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(otpcode);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim("id", email) }),
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }
S S
  • 19
  • 3

1 Answers1

1

Injecting the middleware will resolve it from the root lifetime, which doesn't have access to the scope. Resolve it from the context provider instead, which has access to the scope

public async Task Invoke(HttpContext context)
{
    // Resolve the context
    var dataService = context.RequestServices.GetRequiredService<AGUSContext>();
    var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

    if (token != null)
        attachUserToContext(context, dataService, token);

    await _next(context);
}
itsdaniel0
  • 1,059
  • 3
  • 11
  • 28