When architecting enterprise web applications that combine traditional MVC Razor views with RESTful APIs—such as digital invoicing integration gateways—developers frequently encounter subtle configuration traps. Two of the most common issues are API endpoints inadvertently returning HTML login pages instead of JSON, and runtime exceptions caused by strict numeric parsing of external financial payloads.
This article explores how to diagnose and resolve these challenges in an ASP.NET Core environment.
1. The Mystery of the HTML Response on API Endpoints
When testing API endpoints via Swagger or an external HTTP client, receiving an HTTP 200 OK or 301/302 status containing a full HTML page (<!DOCTYPE html>) is a classic symptom of an authentication routing conflict.
The Root Cause
In many enterprise applications, developers enforce a global authorization policy to secure all portal views:
C#
builder.Services.AddControllersWithViews(options =>
{
var globalAuthorizePolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(globalAuthorizePolicy));
});
When this global filter is active, it intercepts requests to your API controllers as well. Because API clients authenticate via custom headers (such as X-Api-Secret) rather than session cookies, the framework views the request as unauthenticated. The Cookie Authentication middleware then redirects the request to /Account/Login, serving an HTML login form instead of a JSON error payload.
The Solution
Step 1: Prevent Cookie Middleware from Redirecting API Routes
Configure your application cookie events to return a clean 401 Unauthorized JSON response for paths starting with /api instead of issuing an HTML redirect:
C#
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/Account/Login";
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json";
return context.Response.WriteAsync("{\"message\": \"Unauthorized: API key required.\"}");
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
}
};
});
Step 2: Align Header Binding Attributes
Ensure that the header name defined in your controller action matches exactly what your client or Swagger definition sends:
C#
[HttpGet("provinces")]
public async Task<IActionResult> GetProvinces([FromHeader(Name = "X-Api-Secret")] string secret)
{
return await ExecuteSafeAsync(() => _fbrApiService.GetProvincesAsync(secret));
}
Note: Casing matters. If Swagger sends X-Api-Secret, your [FromHeader(Name = "...")] attribute must match identically to prevent null binding and unintended model state errors.
2. Preventing FormatException Crashes During Financial Data Parsing
In tax and digital invoicing integration platforms, incoming data payloads often contain string representations of numeric values (prices, tax rates, quantities). Using strict parsing methods like decimal.Parse() can easily crash your pipeline if an unexpected format, empty string, or null value arrives.
The Problem
Consider a line-item calculation routine in a processing service:
C#
// Throws a FormatException if item.Rate is null, empty, or formatted incorrectly
decimal rate = decimal.Parse(item.Rate);
When this fails unhandled, it triggers your exception-handling middleware, resulting in an internal server error response.
The Solution: Defensive Parsing
Replace strict parsing with safe parsing patterns (decimal.TryParse) combined with appropriate fallback logic and structured logging:
C#
if (!decimal.TryParse(item.Rate, out decimal rate))
{
_logger.LogWarning("Invalid tax rate format received for item code: {ItemCode}. Defaulting to 0.", item.ItemCode);
rate = 0m;
}
By ensuring that transient parsing anomalies are handled gracefully rather than crashing the request thread, you maintain high system resilience and prevent pipeline interruptions.
Summary Best Practices
Separate Concerns: Keep API routing distinct from MVC UI routing. Use explicit controller inheritance or attributes (
[AllowAnonymous]) where appropriate.Inspect Middleware Order: Ensure exception-handling and authentication middleware are registered in the correct sequence in
Program.cs.Validate Payload Formats: Always use
TryParseextensions when processing external financial strings or government gateway payloads.

Join the conversation! Your thoughts help the community grow.