Add support for optional FromBody parameters#22634
Conversation
7c8d4ea to
d57ed85
Compare
|
I'll fix the source build. Just wanted to vet the design. |
javiercn
left a comment
There was a problem hiding this comment.
Changes look solid, I would need to look a bit more in depth to see if we are missing something since I'm not an expert in this area.
dougbu
left a comment
There was a problem hiding this comment.
Please change the IAllowEmptyInputInBodyModelBinding definition.
More generally, I'm unsure whether this approach is better or worse than a new MvcOption.AllowEmptyInputInBodyModelBindingIfSet option. We could implement that using ApiParameterDescription.DefaultValue.
| /// <remarks> | ||
| /// When configured, takes precedence over <see cref="MvcOptions.AllowEmptyInputInBodyModelBinding"/>. | ||
| /// </remarks> | ||
| public bool AllowEmptyInputInBodyModelBinding |
There was a problem hiding this comment.
Suggest the property in IAllowEmptyInputInBodyModelBinding should be non-nullable too. I don't see a use case for a tri-state property here.
There was a problem hiding this comment.
I was looking at being able to distinguish these two scenario:
.AddControllers(options => options.AllowEmptyInputInBodyModelBinding = true);
...
public IActionResult Post([FromBody(AllowEmptyInputInBodyModelBinding = false)] /* this API always require a body */ LoginModel model)
public IActionResult Post([FromBody] /* I'm ok with whatever was configured in MvcOptions */ CommentModel model)There was a problem hiding this comment.
Then this property should be of type bool?
There was a problem hiding this comment.
Unfortunately attributes cannot have nullable properties that can be assigned to: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/attributes#attribute-parameter-types. We could create an enum type to represent it. While it might be more correct to have an explicit distinction between fallback to 'system default' vs 'explicitly false', users don't really query the attribute so it seems like overkill.
There was a problem hiding this comment.
Perhaps overkill but the tri-state approach you want won't work as long as the only IAllowEmptyInputInBodyModelBinding implementation has a non-nullable bool.
There was a problem hiding this comment.
The interface IAllowEmptyInputInBodyModelBinding is non-public. It's largely a result of weird layering - BindingInfo is in Abstractions, FromBody is in Mvc.Core. We're free to assign it the shape we think works best.
There was a problem hiding this comment.
[FromBody(AllowEmpty = AllowEmptyBodyBehavior.Default)]
[FromBody(AllowEmpty = AllowEmptyBodyBehavior.Reject)]
[FromBody(AllowEmpty = AllowEmptyBodyBehavior.Allow)]
enum AllowEmptyBodyBehavior
{
Default,
Reject,
Allow
}
|
|
||
| _options = options; | ||
| _formatters = formatters; | ||
| _readerFactory = readerFactory.CreateReader; |
There was a problem hiding this comment.
Messed up. Will undo
|
Thanks both of you for the quick review. As @dougbu, relying on the default value of the parameters would have been super nice and most intuitive. I had hoped that's what we could do but there are a few issues with it that made me use this approach: a) We don't currently have access to parameter values in the binder \ binder factory. The best way I could think of resolving this is by adding b) Relying on default parameter values alone doesn't help solve it for properties. It would be nice to solve the problem for both kinds of bound types - parameters and properties. Using a property was something a user suggested - aspnet/Mvc#6920 (comment) and it has a fair number of upvotes so it doesn't seem entirely unappealing. |
|
@pranavkm got it, thanks for the explanation. That just leaves the |
|
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
|
Hello @pranavkm! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
| { | ||
| /// <summary> | ||
| /// Uses the framework default behavior for processing empty bodies. | ||
| /// This is typically configured using <c>MvcOptions.AllowEmptyInputInBodyModelBinding</c> |
There was a problem hiding this comment.
End comment with another period
* Add support for optional FromBody parameters Fixes #6878 * Fixup nullable * Changes per API review
Fixes #6878
public enum EmptyBodyBehavior { Default = 0, Allow = 1, Disallow = 2, } public partial class FromBodyAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata { public FromBodyAttribute() { } + public EmptyBodyBehavior EmptyBodyBehavior { get { throw null; } set { } } } public partial class BindingInfo { public BindingInfo() { } public BindingInfo(Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo other) { } + public EmptyBodyBehavior EmptyBodyBehavior { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class ApiParameterDescription { public ApiParameterDescription() { } + public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }