Skip to content

Conversation

@captainsafia
Copy link
Member

Closes #6061.

@ghost ghost added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Jan 1, 2022
@captainsafia captainsafia force-pushed the analyzer-valid-problem branch 2 times, most recently from 542231c to 2cfce95 Compare January 3, 2022 22:56
@captainsafia captainsafia force-pushed the analyzer-valid-problem branch from 2cfce95 to 35282d9 Compare January 3, 2022 23:01
@captainsafia captainsafia marked this pull request as ready for review January 4, 2022 01:23
/// </summary>
/// <returns>The created <see cref="BadRequestObjectResult"/> for the response.</returns>
[NonAction]
[DefaultStatusCode(StatusCodes.Status400BadRequest)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind this, but is it super tricky to put the attribute on the return value (because it's kinda more appropriate). Either way it's super nit-picky.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, that's what I was originally trying to do but I ran into limitations with the Roslyn API when parsing the return method. If you have an action like this:

public IActionResult Foo()
{
  return ValidationProblem();
}

We're able to identify that ValidationProblem was invoked and examine the attributes on the ValidationProblem method pretty easily.

If the ValidationProblem looked something like this:

public IActionResult ValidationProblem()
{
   return new FooResult(); // Where `FooResult` has `DefaultStatusCode` attribute
}

We can't peek into the type returned from ValidationProblem and examine the attributes on it, particularly for the case of ValidationProblem since that method is defined in an assembly separate from the source assembly (and probably other shorthand methods as well).


using Microsoft.AspNetCore.Http;

namespace Microsoft.AspNetCore.Mvc.Api.Analyzers._OUTPUT_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really update these tests to use the new analyzer infrastructure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it might be helpful if we added a list of test areas to #36300 and used that to help us push through on that work.


// If the type is not annotated with a default status code, then examine
// the attributes on any invoked method returning the type.
if (defaultStatusCodeAttribute is null && returnedValue.Syntax is InvocationExpressionSyntax targetInvocation)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precedence is here a little wonky. I would think putting something on the method would be more explicit than putting it on the type. Should we prefer an attribute on the method when specified over the attribute on the type? For instance, the method could do things like configure a non-default status code.

Copy link
Member Author

@captainsafia captainsafia Jan 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already prioritize the attribute on the method when specified (e.g. the user is calling MethodThatReturnsIActionResult in the scenario below) over the attribute in the type returned inside MethodThatReturnsIActionResult.

Are you referring to being able to use the DefaultStatusCode attribute on the action method?

public IActionResult MethodThatReturnsIActionResult()
{
   return FooResult();
}

public class FooResult
{
}

public IActionResult GetFoo()
{
  return MethodThatReturnsIActionResult();
}

public IActionResult GetFoo2()
{
  return new FooResult();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I was going for this:

[DefaultStatusCode(421)] public override BadActionResult BadResult() => new StatusCodeResult(421);

Looking at the code, it looked we would infer the default as 400 (because that's what BadActionResult is annotated with) rather than 421 even though it's "closer" to the callsite.

@captainsafia captainsafia added the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Jan 4, 2022
@ghost
Copy link

ghost commented Jan 4, 2022

Thank you for your API proposal. I'm removing the api-ready-for-review label. API Proposals should be submitted for review through Issues based on this template.

@ghost ghost removed the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Jan 4, 2022
Copy link
Contributor

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My feedback is mostly nitpicky, this PR is fine as-is

@captainsafia captainsafia enabled auto-merge (squash) January 4, 2022 17:47
@captainsafia captainsafia merged commit c76e108 into dotnet:main Jan 4, 2022
@ghost ghost added this to the 7.0-preview1 milestone Jan 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API Analyzer doesn't recognize ControllerBase.ValidationProblem.

2 participants