By following samples I wrote a simple middleware to log some request details. I am not sure why Middleware constructor which takes RequestDelegate doesn't fire with each request. I simply added a breakpoint on Middleware constructor and fired multiple request one by one from browser, I can see Middleware constructor getting fired only first time. On subsequent call it doesn't call constructor. Is this correct? Why?
Also, does it mean that If I have a scoped service (generating GUID) and if middleware constructor is taking this scoped service as one of the parameter, my GUID will be the same for all request? Should I not pass scoped service as constructor parameter?
My middleware is as follows: As you can see I am passing IRequestIdService as constructor parameter and all request have same guid.
public class RequestLoggerMiddleware { private readonly RequestDelegate _next; private readonly IUserProfileService _userProfileService; private readonly IRequestIdService _requestIdService; private readonly ILogger<RequestLoggerMiddleware> _logger; public RequestLoggerMiddleware(RequestDelegate next, IUserProfileService userProfileService, IRequestIdService requestIdService, ILogger<RequestLoggerMiddleware> logger) { _next = next; _userProfileService = userProfileService; _requestIdService = requestIdService; _logger = logger; } public async Task Invoke(HttpContext context) { var auditSummary = new AuditSummary { AuditId = _requestIdService.RequestId, GPID = _userProfileService.GPID, Method = context.Request.Method, Path = context.Request.Path, }; _logger.LogInformation($"{auditSummary.AuditId} - {auditSummary.GPID} - {auditSummary.Method} - {auditSummary.Path}"); await _next.Invoke(context); } }
If I change my code to look as follows then it works fine. Which means I shouldn't pass UserProfileService in constructor too.
public class RequestLoggerMiddleware { private readonly RequestDelegate _next; private readonly IUserProfileService _userProfileService; private IRequestIdService _requestIdService; private readonly ILogger<RequestLoggerMiddleware> _logger; public RequestLoggerMiddleware(RequestDelegate next, IUserProfileService userProfileService, ILogger<RequestLoggerMiddleware> logger) { _next = next; _userProfileService = userProfileService; _logger = logger; } public async Task Invoke(HttpContext context) { _requestIdService = context.RequestServices.GetRequiredService<RequestIdService>(); var auditSummary = new AuditSummary { AuditId = _requestIdService.RequestId, GPID = _userProfileService.GPID, Method = context.Request.Method, Path = context.Request.Path, }; _logger.LogInformation($"{auditSummary.AuditId} - {auditSummary.GPID} - {auditSummary.Method} - {auditSummary.Path}"); await _next.Invoke(context); } }
Towards the end of the article (http://dotnetliberty.com/index.php/2015/12/28/asp-net-5-scoped-dependencies/) author describes "Singleton Captures Scoped". That is what I am facing.
Anyone can explain?