question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ProblemDetailsService Can Simplify Writers Evaluation

See original GitHub issue

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:

https://github.com/dotnet/aspnetcore/blob/5918bc9db2099f90cc6f5b5db43a8d16f5dc89df/src/Http/Http.Extensions/src/ProblemDetailsService.cs#L42

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.

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
brunolins16commented, Feb 23, 2023

@commonsensesoftware that is right. I ended up implementing everything as part of another work I did. Sorry if you spent time in this PR.

1reaction
brunolins16commented, Nov 23, 2022

Sure. I can spin up a PR.

What is gained (or retained) by keeping the branch for if (_writers.Length == 1)? Since `writers supports indexing, I don’t see any additional allocations or other benefits. I’m just seeing another branch that does the same thing as the loop. The net effect will be the same and is seeming unnecessary.

Just curious. If there is some performance benefit, I would like to learn about it for future reference.

Actually, you are right. I just noticed that writers is an array already, so, I think no extra allocations.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Best way to implement the ProblemDetails in Asp.Net Core ...
I could able to solve the issue by using the below code in ConfigureServices method of Startup.cs. services.AddMvc().
Read more >
RFC 7807 - Problem Details for HTTP APIs
RFC 7807 Problem Details March 2016 response body in a machine-readable format, the client can treat it appropriately; for example, triggering a transfer...
Read more >
Using the ProblemDetails Class in ASP.NET Core Web API
ProblemDetails class in ASP.NET Core Web APIs helps us to standardize our error handling and have better communication with API clients.
Read more >
RFC 7807: error handling standard for APIs
RFC 7807 make possible to support multiple errors thanks to extensions as can happen in validation use-cases: a response report the reference ...
Read more >
What's new in ASP.NET Core 7.0
As part of the work to simplify authentication, when there's only a ... The problem details service implements the IProblemDetailsService ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found