-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Support DefaultStatusCode annotation on methods #39255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
542231c to
2cfce95
Compare
2cfce95 to
35282d9
Compare
| /// </summary> | ||
| /// <returns>The created <see cref="BadRequestObjectResult"/> for the response.</returns> | ||
| [NonAction] | ||
| [DefaultStatusCode(StatusCodes.Status400BadRequest)] |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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_ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
src/Mvc/Mvc.Api.Analyzers/src/ActualApiResponseMetadataFactory.cs
Outdated
Show resolved
Hide resolved
|
|
||
| // 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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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();
}There was a problem hiding this comment.
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.
|
Thank you for your API proposal. I'm removing the |
pranavkm
left a comment
There was a problem hiding this 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
Closes #6061.