Skip to content

ProblemDetailsService Can Simplify Writers Evaluation #45052

@commonsensesoftware

Description

@commonsensesoftware

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

The ProblemDetailsService implementation uses the last registered IProblemDetailsWriter where CanWrite returns true as seen at:

for (var i = 0; i < _writers.Length; i++)

Although a micro-optimization, the loop should be processed in reverse. As soon as a writer on the tail end can write the ProblemDetails, then the loop can break. In fact, the entire implementation can be simplified to:

    public ValueTask WriteAsync(ProblemDetailsContext context)
    {
        ArgumentNullException.ThrowIfNull(context);
        ArgumentNullException.ThrowIfNull(context.ProblemDetails);
        ArgumentNullException.ThrowIfNull(context.HttpContext);

        if (context.HttpContext.Response.HasStarted ||
            context.HttpContext.Response.StatusCode < 400 ||
            _writers.Length == 0)
        {
            return ValueTask.CompletedTask;
        }

-        IProblemDetailsWriter? selectedWriter = null;

-        if (_writers.Length == 1)
-        {
-            selectedWriter = _writers[0];

-            return selectedWriter.CanWrite(context) ?
-                selectedWriter.WriteAsync(context) :
-                ValueTask.CompletedTask;
-        }

-       for (var i = 0; i < _writers.Length; i++)
+       for (var i = _writers.Length - 1; i >= 0; i--)
        {
+            var selectedWriter = _writers[i];
-            if (_writers[i].CanWrite(context))
+            if (selectedWriter.CanWrite(context))
-            {
-                selectedWriter = _writers[i];
-                break;
+                return selectedWriter.WriteAsync(context);
-            }
        }

-        if (selectedWriter != null)
-        {
-            return selectedWriter.WriteAsync(context);
-        }

        return ValueTask.CompletedTask;
    }

Expected Behavior

IProblemDetailsService.WriteAsync should execute with the fewest number of operations necessary.

Steps To Reproduce

var builder = WebApplication.CreateBuilder( args );

builder.Services.AddProblemDetails();

Exceptions (if any)

No response

.NET Version

7.0.100

Anything else?

Happy to submit a PR if the proposed changes are accepted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-problem-detailshelp wantedUp for grabs. We would accept a PR to help resolve this issueold-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions