-
Notifications
You must be signed in to change notification settings - Fork 20
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
Release notes? #48
Comments
No official release notes 😞. The bulk of changes came from #45. This change-set added features to allow class-level bind-ordering (so this doesn't need explicitly defined on each property) and the ability to see how a property was set (by implementing Here's the change-set for the README: 7275737#diff-04c6e90faac2675aa89e2176d2eec7d8 All changes should be backwards-compatible. I didn't come across anything glaring even though I made several updates to the internal binding-process. Do you have a small working sample you could submit that I could review with the current release-version? |
0.18.0 also causes issues for me as well. .NET Core 3.1.
Behavior in 0.17.0: Route parameter Prop1 would be correctly populated when doing a POST to this endpoint Let me know if you need a more fully working example. I'll try to go through the diff to see if I can spot something. |
I've created a gist with a test that works on 0.17.0 and doesn't on 0.18.0. It turns out the issue for me was using a Guid for a route value causes it to be all 0's in 0.18.0. The workaround is to use a Guid? or a string. |
Right now for me there’s no workaround as I don’t want to change 200 api endpoint :( Thank you @bkaid for adding a gist to reproduce the issue. I missed the notification from @billbogaiv |
I'll step through code using that |
I've identified the problem, but am not sure there will be a fix... TL;DRExplicitly set the binding of the affected properties so
|
protected static IEnumerable<string> FallbackBindingOrder = new[] { Source.Body, Source.Form, Source.Route, Source.QueryString, Source.Header }; |
Make a global change so the ability to bind to a property doesn't stop at the first-match:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddHybridModelBinder(options => options.Passthrough = true);
}
IHybridBoundModel
. 0.18.1-alpha-2
or higher will eventually fix the last-part.
Full-story explanation
The biggest change from 0.17.0
to 0.18.0
was to fix that a property couldn't have bind-ordering where Source.Body
wasn't the first-option:
[HybridBindProperty(Source.Route, Source.Query, Source.Body)]
...would internally bind Source.Body
first (since IModelBinder
comes before IValueProvider
).
I suspect most use-cases wanted Source.Body
first anyway so it was probably never seen as a "problem" by anyone using the library.
Fast-forward to 0.18.0
and I introduced a wrapper around the result of IModelBinder
, called BodyValueProvider
, so I could properly allow the bind-ordering specified above (and logging to know how a property was bound). By-default, HybridModelBinding
uses the ASP.NET Core implementation of BodyModelBinder. Given the following model and request:
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
}
POST
{
"name": "Bill"
}
using BodyModelBinder
will create an instance of Person
:
{
"Id": "00000000-0000-0000-0000-000000000000',
"Name": "Bill"
}
There's just not enough info. coming back from BodyModelBinder.BindModelAsync to know whether Id
was bound from the request or is the default-value. I played-around with checking for default(Type)
, but that creates its own problems since an empty-Guid
(or any non-null value-type) could be sent in the request and HybridModelBinding
wouldn't know the difference).
I also thought about creating a custom BodyModelBinder
to use by-default which would try and do those extra features, but then anyone deciding to use the ASP.NET Core-version might not understand why the behaviors were different... maybe no one even cares to use HybridModelBinding
defining their own binders/value-providers, so that could still be an option.
I'm open to other suggestions.
IMO, if the request has a value at any point in the ordering, set the value. I mean, if I have a value in the route If I have the ordering as: Body, Route. I don't care what the body set, i want the route to set the value. If the ordering is Route, Body, then what ever was sent on the payload should override the Route. The thing is, I don't understand why you would ever bind the body last. It doesn't make any sense and I've been pondering this a few days and I cannot think of a single valid scenario. Any scenario where you are binding from multiple sources, you want to bind the other sources on top of the body. Because you're taking an id or such from the route/query string. Or you're adding header version. IMO I would remove the complexity of allowing binding Body last. Body + [Ordered Route/Query/Headers] (so only allow ordering of whats applied on top of the body) |
New `BodyValueProvider` behavior tracks request body-keys so the model-binder instantiated model's properties are not seen as "bound" unless they were actually in the request-body. This prevents false-positives during the bind-process. Previous behavior assumed all properties via a model-binder came from the request. Implements solution for #48 (comment)
I think I'm gonna be stuck on 17 forever :( |
Are there release notes for the changes from 0.17.0 to 0.18.0?
The model binding stopped working when I upgraded and I can't figure out what changed.
The text was updated successfully, but these errors were encountered: