-
Notifications
You must be signed in to change notification settings - Fork 10k
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
Add DateOnly and TimeOnly to MVC Model Binding #45243
Conversation
src/Mvc/Mvc.Core/src/ModelBinding/Binders/DateOnlyModelBinderProvider.cs
Outdated
Show resolved
Hide resolved
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.
Congrats on your first PR in aspnetcore! 🎉
Adding the blocked label pending the approval and resolution of #45376. |
@@ -74,6 +74,8 @@ public void Configure(MvcOptions options) | |||
options.ModelBinderProviders.Add(new ArrayModelBinderProvider()); | |||
options.ModelBinderProviders.Add(new CollectionModelBinderProvider()); | |||
options.ModelBinderProviders.Add(new ComplexObjectModelBinderProvider()); | |||
options.ModelBinderProviders.Add(new DateOnlyModelBinderProvider()); | |||
options.ModelBinderProviders.Add(new TimeOnlyModelBinderProvider()); |
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.
Can these new IModelBinderProvider
s ever get hit outside of unit tests? I cloned this PR and added the following lines to MvcSandbox's HomeController
.
public class HomeController : Controller | |
{ | |
[ModelBinder] | |
public string Id { get; set; } | |
public IActionResult Index() | |
{ | |
return View(); | |
} | |
} |
[ModelBinder]
public TimeOnly Time { get; set; }
And then made a request to /?Id=3&Time=12:34:56%20PM
and added breakpoints. The Time got populated by the TryParseModelBinderProvider
added by @brunolins16 in #40233. Since that's added before these providers, it gets first crack at binding DateOnly
and TimeOnly
.
For this reason and to maintain back compat, we put TryParseModelBinderProvider
after DateTimeModelBinderProvider
. Even if we remove the TryParseModelBinderProvider
, the SimpleTypeModelBinderProvider
would handle this first as well using TypeConverter
.
options.ModelBinderProviders.Add(new DateTimeModelBinderProvider()); | |
options.ModelBinderProviders.Add(new TryParseModelBinderProvider()); | |
options.ModelBinderProviders.Add(new SimpleTypeModelBinderProvider()); |
Since we don't have any back compat concerns for DateOnly
and TimeOnly
, I'm not sure we need these. It does allow customizing DateTimeStyles
if you construct the providers yourself and add them manually, but I don't like having to maintain providers for each possible type.
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.
@halter73 Are there any differences in behavior between the TryParse implementation and the concrete modelbinders? Or any other concern like perf? If the TryParse implementation supports all of them, should we get rid of the DateTime and DateTimeOffset modelbinders?
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 would like to get rid of the DateTime
and DateTimeOffset
model binders, but I don't think it's worth potentially breaking working code. @brunolins16 What do you think?
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.
@halter73 I do not think most people will change those binders directly. We can remove them from 8.0, make an announcement in preview1 and see if someone is broken by it.
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.
As reported here , it could potentially be break and was decided (I don't have the historical reason) to create specific binders for them even though the simpletypebinder supported them a long ago. That said I believe this is a worthy investigation and we don't need to delete them and instead just remove the default registration and let the binder available for manual registration.
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.
Here is a potential reason why the specific binders were created #34591 (comment)
Great point, this was an essential part of getting DateTime
binding correct. That being said, DateTimeStyles.AdjustToUniversal
is not supported for DateOnly
and TimeOnly
so the same requirement is not there.
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, the only benefit I see in have those two new binders, is allow users to customize the DateTimeStyles
creating their own ModelBinderProviders
.
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.
Suggestion 💡: What if we add those two new Binder
to allow users customization, without the Providers
(no registration), and let the TryParse/Converter binder do the work by default.
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.
These are the DatetimeStyles
when using the TryParse binder:
aspnetcore/src/Shared/ParameterBindingMethodCache.cs
Lines 130 to 135 in 5c62d0f
var dateTimeStyles = type switch | |
{ | |
Type t when t == typeof(DateTime) => DateTimeStyles.AdjustToUniversal | DateTimeStyles.AllowWhiteSpaces, | |
Type t when t == typeof(DateTimeOffset) => DateTimeStyles.AssumeUniversal | DateTimeStyles.AllowWhiteSpaces, | |
_ => DateTimeStyles.AllowWhiteSpaces | |
}; |
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.
Yep, DateTimeStyles.AllowWhiteSpaces
is what I currently have for these proposed providers. While writing them I found that the only supported styles for TimeOnly
and DateOnly
were the ones pertaining to white space, but I can't seem to find a doc page to back that up.
Also, do you think there's any gain/loss when TryParse is used over any of the other providers/binders? I see that TryParse goes before SimpleType.
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.
Overall looks great, I think we are missing some E2E test coverage, as @halter73 pointed out.
Thanks for that but those types are already |
Hi @brunolins16. It looks like you just commented on a closed PR. The team will most probably miss it. If you'd like to bring something important up to their attention, consider filing a new issue and add enough details to build context. |
Sorry closed by mistake. |
@brunolins16 Yep, sounds like I need to make that docs PR regardless of the outcome of this one. |
} | ||
else if (type == typeof(DateOnly)) | ||
{ | ||
model = DateOnly.Parse(value, valueProviderResult.Culture, _supportedStyles); |
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 recommend the TryParse
here to avoid the exception
} | ||
else if (type == typeof(TimeOnly)) | ||
{ | ||
model = TimeOnly.Parse(value, valueProviderResult.Culture, _supportedStyles); |
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 recommend the TryParse
here to avoid the exception
Closing this PR since TryParseModelBinder already covers this use case with no additional API required |
Add DateOnly and TimeOnly to MVC Model Binding
Adds nullable
DateOnly
andTimeOnly
to list of model binding simple types.Description
Part of the effort tracked in #34591 to add
DateOnly
andTimeOnly
support to Model binding as well as Blazor/regular routing.The logic almost exactly matches the implementation for
DateTime
with the exception ofDateTimeStyles.AdjustToUniversal
being included as a supported style as this style is not supported by theDateOnly
andTimeOnly
types.On the completion and merge of this PR, I will create an additional PR to add
DateOnly
andTimeOnly
to our list of supported types.