Skip to main content

Add problem-details MVC conventions

When building APIs with ASP.NET Core MVC, the framework provides built-in mechanisms for handling client errors and generating responses. However, to ensure consistency between MVC-generated errors (like validation failures) and the custom error handling provided by Middleware, you must align the MVC conventions with the Middleware's ProblemDetails logic.

The AddProblemDetailsConventions extension method in Hellang.Middleware.ProblemDetails.Mvc establishes this alignment by modifying how MVC handles error responses. Specifically, it:

  1. Replaces the Default Factory: It swaps the standard MVC ProblemDetailsFactory with the ProblemDetailsFactory used by Middleware, ensuring that all ProblemDetails objects are created using the same configuration.
  2. Disables Default Mapping: It configures ApiBehaviorOptions to turn off the built-in ClientErrorMapping, preventing MVC from generating its own default error responses that might conflict with your custom middleware logic.
  3. Applies Application Models: It registers a ProblemDetailsApplicationModelProvider to automatically add ProducesErrorResponseTypeAttribute to controllers decorated with ApiControllerAttribute.
  4. Transforms Results: It sets up filters to transform ObjectResult instances containing strings into structured ProblemDetails responses.

To register these conventions, call the extension method on your IServiceCollection during the service configuration phase. The method follows a fluent interface pattern, returning the same IServiceCollection instance to allow for further chaining.

using System;
using Hellang.Middleware.ProblemDetails.Mvc;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// Register the MVC conventions for ProblemDetails.
// This returns the same IServiceCollection instance for chaining.
var returnedServices = services.AddProblemDetailsConventions();

// Verify the public registration contract: the method must return the original collection.
if (!object.ReferenceEquals(services, returnedServices))
{
throw new InvalidOperationException("AddProblemDetailsConventions did not return the original IServiceCollection.");
}