-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New TryParseModelBinder #40233
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
New TryParseModelBinder #40233
Changes from all commits
df4b6c8
a695fec
f1712a2
d088379
df3a6a4
8c54730
4cc18a7
5bff268
81a2408
17866fd
c89d9e2
fe3d122
b3cff44
e73543d
248dc11
dcc5fae
d2ef7b8
d9ff2d0
50dfb9d
748b095
83a28d2
a6e3939
c914e70
d6a8c52
01c0dd6
b730ad4
2d6ca53
d1203e6
47708fe
5d3c7b1
49fdd21
92dd9c5
7a07a9a
f292992
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,9 @@ | |
| using System.Diagnostics; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Linq; | ||
| using System.Linq.Expressions; | ||
| using System.Reflection; | ||
| using Microsoft.AspNetCore.Http; | ||
| using Microsoft.AspNetCore.Mvc.Abstractions; | ||
| using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; | ||
| using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; | ||
|
|
@@ -25,6 +27,8 @@ public abstract class ModelMetadata : IEquatable<ModelMetadata?>, IModelMetadata | |
| /// </summary> | ||
| public static readonly int DefaultOrder = 10000; | ||
|
|
||
| private static readonly ParameterBindingMethodCache ParameterBindingMethodCache = new(); | ||
|
|
||
| private int? _hashCode; | ||
| private IReadOnlyList<ModelMetadata>? _boundProperties; | ||
| private IReadOnlyDictionary<ModelMetadata, ModelMetadata>? _parameterMapping; | ||
|
|
@@ -434,10 +438,10 @@ internal IReadOnlyDictionary<ModelMetadata, ModelMetadata> BoundConstructorPrope | |
| /// </summary> | ||
| /// <remarks> | ||
| /// A complex type is defined as a <see cref="Type"/> without a <see cref="TypeConverter"/> that can convert | ||
| /// from <see cref="string"/>. Most POCO and <see cref="IEnumerable"/> types are therefore complex. Most, if | ||
| /// not all, BCL value types are simple types. | ||
| /// from <see cref="string"/> and without a <c>TryParse</c> method. Most POCO and <see cref="IEnumerable"/> types are therefore complex. | ||
| /// Most, if not all, BCL value types are simple types. | ||
| /// </remarks> | ||
| public bool IsComplexType { get; private set; } | ||
| public bool IsComplexType => !IsConvertibleType && !IsParseableType; | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether or not <see cref="ModelType"/> is a <see cref="Nullable{T}"/>. | ||
|
|
@@ -475,6 +479,17 @@ internal IReadOnlyDictionary<ModelMetadata, ModelMetadata> BoundConstructorPrope | |
| /// </remarks> | ||
| public Type UnderlyingOrModelType { get; private set; } = default!; | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether or not <see cref="ModelType"/> has a TryParse method. | ||
| /// </summary> | ||
| internal virtual bool IsParseableType { get; private set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether or not <see cref="ModelType"/> has a <see cref="TypeConverter"/> | ||
| /// from <see cref="string"/>. | ||
| /// </summary> | ||
| internal bool IsConvertibleType { get; private set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating the NullabilityState of the value or reference type. | ||
| /// </summary> | ||
|
|
@@ -521,6 +536,22 @@ internal void ThrowIfRecordTypeHasValidationOnProperties() | |
| } | ||
| } | ||
|
|
||
| internal static Func<ParameterExpression, Expression, Expression>? FindTryParseMethod(Type modelType) | ||
| { | ||
| try | ||
| { | ||
| modelType = Nullable.GetUnderlyingType(modelType) ?? modelType; | ||
| return ParameterBindingMethodCache.FindTryParseMethod(modelType); | ||
| } | ||
| catch (InvalidOperationException) | ||
| { | ||
| // The ParameterBindingMethodCache.FindTryParseMethod throws an exception | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion - we could update
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. I will open a new PR just for that, ok? |
||
| // when an wrong try/parse method is detected | ||
| // but we don't need this behavior here and return null is enough | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| [MemberNotNull(nameof(_parameterMapping), nameof(_boundConstructorPropertyMapping))] | ||
| private void CalculateRecordTypeConstructorDetails() | ||
| { | ||
|
|
@@ -616,7 +647,8 @@ private void InitializeTypeInformation() | |
| { | ||
| Debug.Assert(ModelType != null); | ||
|
|
||
| IsComplexType = !TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string)); | ||
| IsConvertibleType = TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string)); | ||
| IsParseableType = ModelMetadata.FindTryParseMethod(ModelType) is not null; | ||
| IsNullableValueType = Nullable.GetUnderlyingType(ModelType) != null; | ||
| IsReferenceOrNullableType = !ModelType.IsValueType || IsNullableValueType; | ||
| UnderlyingOrModelType = Nullable.GetUnderlyingType(ModelType) ?? ModelType; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.