My .NET CORE API Custom middleware is being ignored when the API receives a message. This middleware is intended to perform some header validation on any given request.
I am expecting the header validation middleware to be called as part of the request so that header.isValid will show the outcome of this validation. When I put a breakpoint in the controller, the header variable is empty.
Am I mis understanidng what middleware can do in expecting it to communicate with the controller. All I need for it to do is act as a gatekeeper against bad requests so I would be open to having it terminate bad requests and allow good ones through as an outcome
What I have tried:
public interface IHeaderIsValid
{
bool isValid { get; set; }
bool fromCMDS { get; set; }
bool fromLocal { get; set; }
Int16 transmittingInstallationID { get; set; }
}
public class HeaderIsValid : IHeaderIsValid
{
public bool isValid { get; set; }
public bool fromCMDS { get; set; }
public bool fromLocal { get; set; }
public Int16 transmittingInstallationID { get; set; }
}
public static class RequestHeaderMiddlewareExtensions
{
public static IApplicationBuilder UseHeaderValidation(this IApplicationBuilder app)
{
return app.UseMiddleware<RequestHeaderMiddleware>();
}
}
public class RequestHeaderMiddleware
{
#region CONSTRUCTORS
public RequestHeaderMiddleware(RequestDelegate next)
{
_next = next;
}
#endregion
#region PUBLIC METHJODS
public async Task Invoke(HttpContext context, IHeaderIsValid header)
{
try
{
header.isValid = false;
bool hasInstallationID = Int16.TryParse(context.Request.Headers.FirstOrDefault(x => x.Key == "InstallationID").Value.ToString(), out this.transmittingInstallationID);
if (!hasInstallationID)
{
throw new NoInstallationIDOnHeaderException("No Installation ID on the Request Header");
}
string fromLocalHeader = context.Request.Headers.FirstOrDefault(x => x.Key == "FromLocal").Value.ToString();
if (fromLocalHeader != string.Empty)
{
bool.TryParse(fromLocalHeader, out this.fromLocal);
}
else
{
this.fromLocal = false;
}
bool hasFromCMDS = bool.TryParse(context.Request.Headers.FirstOrDefault(x => x.Key == "FromCMDS").Value.ToString(), out this.fromCMDS);
if (!hasFromCMDS)
{
this.fromCMDS = false;
}
if (this.fromCMDS && this.fromLocal)
{
throw new FromCMDSAndFromLocalSetException("The FromLocal and FromCMDS indicators are both set on the request header");
}
if (!this.fromCMDS && !this.fromLocal)
{
throw new NoOriginSetException("One of The FromLocal and FromCMDS indicators must be set on the request header");
}
}
catch (Exception ex)
{
throw ex;
}
header.isValid = true;
await _next(context);
}
#endregion
#region PRIVATE VARIABLES
private readonly RequestDelegate _next;
#endregion
#region PUBLIC VARIABLES
public Int16 transmittingInstallationID;
public bool fromCMDS;
public bool fromLocal;
#endregion
}
Then in startup.cs (ConfigureServices is trimmed for brevity)
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IHeaderIsValid, HeaderIsValid>();
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddLog4Net();
app.UseCors("default");
app.UseAuthentication();
app.UseMvc();
app.UseHeaderValidation();
}
}
}
Here is a snippet from the controller:
[Route("LDH/[controller]")]
[ApiController]
public class SalesController : ControllerBase
{
[Authorize]
[HttpPost("ProcessPayment")]
public async Task<ActionResult> ProcessPayment(WorkingTicket ticketDetails)
{
if (!header.isValid)
{
ModelState.AddModelError("BadHeader", "Request header is invalid");
return BadRequest(ModelState);
}
Return OK();
}
private IHeaderIsValid header;
}