-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Improve error messages for implicit and explicit FromBody attribute in Minimal API #35086 #35188
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
Improve error messages for implicit and explicit FromBody attribute in Minimal API #35086 #35188
Conversation
I think we should split this into two PRs. One for throwing for multiple from-body parameters during Create() and another for throwing for not finding a body when one is expected during the request. |
if (parameterName is not null && factoryContext.TrackedParameters.ContainsKey(parameterName)) | ||
{ | ||
factoryContext.TrackedParameters.Remove(parameterName); | ||
factoryContext.TrackedParameters.Add(parameter.Name!, "We failed to infer this parameter. Did you forget to inject it as a Service in the DI container?"); |
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.
factoryContext.TrackedParameters.Add(parameter.Name!, "We failed to infer this parameter. Did you forget to inject it as a Service in the DI container?"); | |
factoryContext.TrackedParameters.Add(parameter.Name!, "UNKNOWN"); |
I think the following is a bit hard to read:
Unhandled exception. System.InvalidOperationException: Failure to infer one or more parameters. Below is the list of parameters we found:
Parameter Source
sampleDTO Body Attribute
userRepo We failed to infer this parameter. Did you forget to inject it as a Service?
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArguments(ParameterInfo[] parameters, FactoryContext factoryContext) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 209
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateTargetableRequestDelegate(MethodInfo methodInfo, RequestDelegateFactoryOptions options, Expression targetExpression) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 170
...
This would be a bit better:
Unhandled exception. System.InvalidOperationException: Failure to infer one or more parameters. Below is the list of parameters we found:
Parameter | Source
----------+------------------
sampleDTO | Body (Attribute)
userRepo | UNKOWN
Did you forget to inject the "UNKNOWN" parameters as a Service?
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArguments(ParameterInfo[] parameters, FactoryContext factoryContext) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 209
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateTargetableRequestDelegate(MethodInfo methodInfo, RequestDelegateFactoryOptions options, Expression targetExpression) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 170
...
Adding the |
and -
would require more than just the suggested fix of course but I think it will help. Can you show what this looks like on the developer exception page?
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.
Also, do we get the same "Failure to infer one or more parameters." error when all the parameters have explicit attributes? If there actually are multiple [FromBody]
attributes we should probably just continue saying that's not allowed instead of saying we couldn't infer the source.
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.
Do we have a logger formatter or console formatter in aspnetcore that I can use ?
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 am hoping an analyzer will prevent the double explicit [FromBody]
right away.
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.
New formatting. Not perfect, visually readable.
Unhandled exception. System.InvalidOperationException: Failure to infer one or more parameters.
Below is the list of parameters that we found:
Parameter |Source
---------------------------------------------------------------------------------
id | Route (Inferred)
dto | Body (Attribute)
dto1 | UNKNOWN
repo | Service (Attribute)
repo1 | UNKNOWN
Did you forget to inject the "UNKNOWN" parameters as a Service?
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArguments(ParameterInfo[] parameters, FactoryContext factoryContext) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 196
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateTargetableRequestDelegate(MethodInfo methodInfo, RequestDelegateFactoryOptions options, Expression targetExpression) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 165
at Microsoft.AspNetCore.Http.RequestDelegateFactory.Create(Delegate action, RequestDelegateFactoryOptions options) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 84
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.
"Did you mean to register the "UNKNOWN" parameters as a Service?"
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.
Unhandled exception. System.InvalidOperationException: Failure to infer one or more parameters.
Below is the list of parameters that we found:
Parameter |Source
---------------------------------------------------------------------------------
id | Route (Inferred)
dto | Body (Attribute)
dto1 | UNKNOWN
repo | Service (Attribute)
repo1 | UNKNOWN
Did you mean to register the "UNKNOWN" parameters as a Service?
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArguments(ParameterInfo[] parameters, FactoryContext factoryContext) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 196
at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateTargetableRequestDelegate(MethodInfo methodInfo, RequestDelegateFactoryOptions options, Expression targetExpression) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 165
at Microsoft.AspNetCore.Http.RequestDelegateFactory.Create(Delegate action, RequestDelegateFactoryOptions options) in C:\Users\rassumani\bench\aspnetcore\src\Http\Http.Extensions\src\RequestDelegateFactory.cs:line 84
@@ -203,6 +217,7 @@ private static Expression CreateArgument(ParameterInfo parameter, FactoryContext | |||
|
|||
if (parameterCustomAttributes.OfType<IFromRouteMetadata>().FirstOrDefault() is { } routeAttribute) | |||
{ | |||
factoryContext.TrackedParameters.Add(parameter.Name, RequestDelegateFactoryConstants.RouteAttribue); |
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.
Great call to add a separate class for all the constants we're introducing here.
@@ -189,6 +190,13 @@ private static Expression[] CreateArguments(ParameterInfo[]? parameters, Factory | |||
args[i] = CreateArgument(parameters[i], factoryContext); | |||
} | |||
|
|||
if(factoryContext.HasMultipleBodyParameters) |
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.
Super nit:
if(factoryContext.HasMultipleBodyParameters) | |
if (factoryContext.HasMultipleBodyParameters) |
@@ -254,6 +267,7 @@ private static Expression CreateArgument(ParameterInfo parameter, FactoryContext | |||
// when RDF.Create is manually invoked. | |||
if (factoryContext.RouteParameters is { } routeParams) | |||
{ | |||
factoryContext.TrackedParameters.Add(parameter.Name, RequestDelegateFactoryConstants.RouteParameter); |
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.
This isn't correct anymore. It's either route or query or either.
Improve error messages for implicit and explicit FromBody attribute in Minimal API #35086
PR Description
This a draft PR to start the conversation on a possible solution for error messages when :
Example:
In the example above, the code changes will keep track of all the request parameters and provide an error message telling the user which parameters we could successfully infer which ones fail. It also adds the parameter source (From Query String, Route, Services, etc.)
We will read the body
httpContext.Request.ReadFromJsonAsync(bodyType)
and throw an exception in CreateContentTypeError method.Exception:
Fixes #35086