I am trying to identify the issue I am facing here with my middleware injection. I have added an 'Audit' trail to my application by forwarding requests via HttpContext to my SQL Server DB which then can be viewed by admins in my application under my Events Controller/View.
My StartUp.cs is as follows:
using AWS_Service_Catalog.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.EntityFrameworkCore;
using AWS_Service_Catalog.Models;
using AWS_Service_Catalog.Data;
using AWS_Service_Catalog.Middleware;
namespace AWS_Service_Catalog
{
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)
{
services.AddDistributedMemoryCache();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
// Handling SameSite cookie according to https://learn.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
options.HandleSameSiteCookieCompatibility();
});
services.AddOptions();
//Adds authentication/authorization via Microsoft Azure AD
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
.AddDownstreamWebApi("AWSServiceCatalogAPI", Configuration.GetSection("DownstreamApi:Scopes"))
.AddInMemoryTokenCaches();
services.AddApiService(Configuration);
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
services.AddRazorPages();
services.AddDbContext<EventLogContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MicrosoftSQLServer")));
//Configuring appsettings section AzureAd, into IOptions
services.AddOptions();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//Production Exception Handler ex: API connection failed will trigger exception routed to /Home/Error
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//Handles User Error: 401, 403, 404, etc. Errors caught must land Application side. Errors occured in API with return 500 and be routed via Exception Handler
app.UseStatusCodePagesWithReExecute("/Home/Error", "?status={0}");
app.UseHttpException();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
//Must include Authentication/Authorization under routing
app.UseAuthentication();
app.UseAuthorization();
app.UseEventLogCaptureMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Server}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
}
My EventLogCaptureMiddleware class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Identity.Web;
using AWS_Service_Catalog.Models;
using AWS_Service_Catalog.Data;
namespace AWS_Service_Catalog.Middleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class EventLogCaptureMiddleware
{
private readonly RequestDelegate _next;
private readonly EventLogContext _context;
public EventLogCaptureMiddleware(RequestDelegate next, EventLogContext context)
{
_next = next;
_context = context;
}
public Task Invoke(HttpContext httpContext)
{
string role;
try
{
role = httpContext.User.Claims.ToArray()[5].Value;
}
catch
{
role = null;
}
var eventLogModel = new EventLogViewModel
{
Timestamp = DateTime.Now,
Role = role,
Method = httpContext.Request.Method,
Upn = httpContext.User.Identity.Name,
Resource = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}{httpContext.Request.Path}{httpContext.Request.QueryString}"
};
_context.Add(eventLogModel);
var tasks = new Task[] { _context.SaveChangesAsync() };
Task.WaitAll(tasks);
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class EventLogCaptureMiddlewareExtensions
{
public static IApplicationBuilder UseEventLogCaptureMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<EventLogCaptureMiddleware>();
}
}
}
I am failing to understand the exact error or the cause. I have looked at this question posted: Cannot resolve scoped service from root provider .Net Core 2
Some elaboration would be wonderful. I can't identify how to resolve this issue until I know what it is. What is interesting to me, this error only occurs when I run my application in IIS Express. Otherwise there seems to be no issue.
Thoughts?