Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Halter <halter73@gmail.com>2022-06-01 04:19:46 +0300
committerStephen Halter <halter73@gmail.com>2022-06-01 04:20:15 +0300
commit1e71d1eec4b278960d5d2752a8fcb57e0bf1196b (patch)
treefdda23bc9f8ebc655a5f5f30c1b07e56801c1844
parent978998cdf15d5a17740629c134095e653cbb6f3e (diff)
Fix nullability of TryUpdateModelAsynchalter73/41886
-rw-r--r--src/Mvc/Mvc.Core/src/ControllerBase.cs4
-rw-r--r--src/Mvc/Mvc.Core/src/ModelBinding/DefaultPropertyFilterProvider.cs4
-rw-r--r--src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs6
-rw-r--r--src/Mvc/Mvc.Core/src/PublicAPI.Unshipped.txt6
-rw-r--r--src/Mvc/Mvc.Core/test/ControllerBaseTest.cs63
5 files changed, 74 insertions, 9 deletions
diff --git a/src/Mvc/Mvc.Core/src/ControllerBase.cs b/src/Mvc/Mvc.Core/src/ControllerBase.cs
index d1c9a840d7..5fddac183d 100644
--- a/src/Mvc/Mvc.Core/src/ControllerBase.cs
+++ b/src/Mvc/Mvc.Core/src/ControllerBase.cs
@@ -2619,7 +2619,7 @@ public abstract class ControllerBase
public async Task<bool> TryUpdateModelAsync<TModel>(
TModel model,
string prefix,
- params Expression<Func<TModel, object>>[] includeExpressions)
+ params Expression<Func<TModel, object?>>[] includeExpressions)
where TModel : class
{
if (model == null)
@@ -2710,7 +2710,7 @@ public abstract class ControllerBase
TModel model,
string prefix,
IValueProvider valueProvider,
- params Expression<Func<TModel, object>>[] includeExpressions)
+ params Expression<Func<TModel, object?>>[] includeExpressions)
where TModel : class
{
if (model == null)
diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/DefaultPropertyFilterProvider.cs b/src/Mvc/Mvc.Core/src/ModelBinding/DefaultPropertyFilterProvider.cs
index 95324dc180..d30748e7de 100644
--- a/src/Mvc/Mvc.Core/src/ModelBinding/DefaultPropertyFilterProvider.cs
+++ b/src/Mvc/Mvc.Core/src/ModelBinding/DefaultPropertyFilterProvider.cs
@@ -27,7 +27,7 @@ public class DefaultPropertyFilterProvider<TModel> : IPropertyFilterProvider
/// Expressions which can be used to generate property filter which can filter model
/// properties.
/// </summary>
- public virtual IEnumerable<Expression<Func<TModel, object>>>? PropertyIncludeExpressions => null;
+ public virtual IEnumerable<Expression<Func<TModel, object?>>>? PropertyIncludeExpressions => null;
/// <inheritdoc />
public virtual Func<ModelMetadata, bool> PropertyFilter
@@ -45,7 +45,7 @@ public class DefaultPropertyFilterProvider<TModel> : IPropertyFilterProvider
}
private static Func<ModelMetadata, bool> GetPropertyFilterFromExpression(
- IEnumerable<Expression<Func<TModel, object>>> includeExpressions)
+ IEnumerable<Expression<Func<TModel, object?>>> includeExpressions)
{
var expression = ModelBindingHelper.GetPropertyFilterExpression(includeExpressions.ToArray());
return expression.Compile();
diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs
index 236a243d7b..34dc03f9c3 100644
--- a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs
+++ b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs
@@ -82,7 +82,7 @@ internal static class ModelBindingHelper
IModelBinderFactory modelBinderFactory,
IValueProvider valueProvider,
IObjectModelValidator objectModelValidator,
- params Expression<Func<TModel, object>>[] includeExpressions)
+ params Expression<Func<TModel, object?>>[] includeExpressions)
where TModel : class
{
if (includeExpressions == null)
@@ -363,7 +363,7 @@ internal static class ModelBindingHelper
/// <param name="expressions">Expressions identifying the properties to allow for binding.</param>
/// <returns>An expression which can be used with <see cref="IPropertyFilterProvider"/>.</returns>
public static Expression<Func<ModelMetadata, bool>> GetPropertyFilterExpression<TModel>(
- Expression<Func<TModel, object>>[] expressions)
+ Expression<Func<TModel, object?>>[] expressions)
{
if (expressions.Length == 0)
{
@@ -385,7 +385,7 @@ internal static class ModelBindingHelper
}
private static Expression<Func<ModelMetadata, bool>> GetPredicateExpression<TModel>(
- Expression<Func<TModel, object>> expression)
+ Expression<Func<TModel, object?>> expression)
{
var propertyName = GetPropertyName(expression.Body);
diff --git a/src/Mvc/Mvc.Core/src/PublicAPI.Unshipped.txt b/src/Mvc/Mvc.Core/src/PublicAPI.Unshipped.txt
index 80b80b3520..fabf768487 100644
--- a/src/Mvc/Mvc.Core/src/PublicAPI.Unshipped.txt
+++ b/src/Mvc/Mvc.Core/src/PublicAPI.Unshipped.txt
@@ -3,6 +3,10 @@
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.DisableImplicitFromServicesParameters.get -> bool
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.DisableImplicitFromServicesParameters.set -> void
Microsoft.AspNetCore.Mvc.ApplicationModels.InferParameterBindingInfoConvention.InferParameterBindingInfoConvention(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider! modelMetadataProvider, Microsoft.Extensions.DependencyInjection.IServiceProviderIsService! serviceProviderIsService) -> void
+*REMOVED* Microsoft.AspNetCore.Mvc.ControllerBase.TryUpdateModelAsync<TModel>(TModel! model, string! prefix, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider! valueProvider, params System.Linq.Expressions.Expression<System.Func<TModel!, object?>!>![]! includeExpressions) -> System.Threading.Tasks.Task<bool>!
+*REMOVED*Microsoft.AspNetCore.Mvc.ControllerBase.TryUpdateModelAsync<TModel>(TModel! model, string! prefix, params System.Linq.Expressions.Expression<System.Func<TModel!, object!>!>![]! includeExpressions) -> System.Threading.Tasks.Task<bool>!
+Microsoft.AspNetCore.Mvc.ControllerBase.TryUpdateModelAsync<TModel>(TModel! model, string! prefix, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider! valueProvider, params System.Linq.Expressions.Expression<System.Func<TModel!, object?>!>![]! includeExpressions) -> System.Threading.Tasks.Task<bool>!
+Microsoft.AspNetCore.Mvc.ControllerBase.TryUpdateModelAsync<TModel>(TModel! model, string! prefix, params System.Linq.Expressions.Expression<System.Func<TModel!, object?>!>![]! includeExpressions) -> System.Threading.Tasks.Task<bool>!
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.TryParseModelBinderProvider
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.TryParseModelBinderProvider.GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext! context) -> Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder?
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.TryParseModelBinderProvider.TryParseModelBinderProvider() -> void
@@ -29,3 +33,5 @@ Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadataProvider.Defa
Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.ModelBinderFactory(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider! metadataProvider, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Mvc.MvcOptions!>! options, System.IServiceProvider! serviceProvider) -> void
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.ParameterBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider! modelMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderFactory! modelBinderFactory, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator! validator, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Mvc.MvcOptions!>! mvcOptions, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void
static Microsoft.AspNetCore.Mvc.ControllerBase.Empty.get -> Microsoft.AspNetCore.Mvc.EmptyResult!
+*REMOVED*virtual Microsoft.AspNetCore.Mvc.ModelBinding.DefaultPropertyFilterProvider<TModel>.PropertyIncludeExpressions.get -> System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression<System.Func<TModel!, object!>!>!>?
+virtual Microsoft.AspNetCore.Mvc.ModelBinding.DefaultPropertyFilterProvider<TModel>.PropertyIncludeExpressions.get -> System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression<System.Func<TModel!, object?>!>!>?
diff --git a/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs b/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs
index deeda17dd2..3b6020a52d 100644
--- a/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs
+++ b/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs
@@ -2728,8 +2728,7 @@ public class ControllerBaseTest
[Theory]
[InlineData("")]
[InlineData("prefix")]
- public async Task
- TryUpdateModel_IncludeExpressionWithValueProviderOverload_UsesPassedArguments(string prefix)
+ public async Task TryUpdateModel_IncludeExpressionWithValueProviderOverload_UsesPassedArguments(string prefix)
{
// Arrange
var valueProvider = new Mock<IValueProvider>();
@@ -2758,6 +2757,57 @@ public class ControllerBaseTest
Assert.NotEqual(0, binder.BindModelCount);
}
+#nullable enable
+ [Fact]
+ public async Task TryUpdateModel_SupportsNullableExpressions()
+ {
+ // Arrange
+ var valueProvider = new Mock<IValueProvider>();
+ valueProvider.Setup(v => v.ContainsPrefix(""))
+ .Returns(true);
+
+ StubModelBinder CreateBinder() => new StubModelBinder(context =>
+ {
+ Assert.Same(
+ valueProvider.Object,
+ Assert.IsType<CompositeValueProvider>(context.ValueProvider)[0]);
+
+ Assert.NotNull(context.PropertyFilter);
+
+ bool InvokePropertyFilter(string propertyName)
+ {
+ var modelMetadata = context.ModelMetadata.Properties[propertyName];
+ Assert.NotNull(modelMetadata);
+ return context.PropertyFilter!(modelMetadata!);
+ }
+
+ Assert.True(InvokePropertyFilter("Include"));
+ Assert.False(InvokePropertyFilter("Exclude"));
+ });
+
+ var binder1 = CreateBinder();
+ var controller1 = GetController(binder1, valueProvider.Object);
+ var model1 = new MyNullableModel();
+
+ // Act
+ await controller1.TryUpdateModelAsync(model1, prefix: "", m => m.Include);
+
+ // Assert
+ Assert.NotEqual(0, binder1.BindModelCount);
+
+ // Arrange (IModelBinder overload)
+ var binder2 = CreateBinder();
+ var controller2 = GetController(binder2, valueProvider.Object);
+ var model2 = new MyNullableModel();
+
+ // Act (IModelBinder overload)
+ await controller2.TryUpdateModelAsync(model2, prefix: "", m => m.Include);
+
+ // Assert (IModelBinder overload)
+ Assert.NotEqual(0, binder2.BindModelCount);
+ }
+#nullable restore
+
[Fact]
public async Task TryUpdateModelNonGeneric_PropertyFilterWithValueProviderOverload_UsesPassedArguments()
{
@@ -3114,6 +3164,15 @@ public class ControllerBaseTest
public string Property3 { get; set; }
}
+#nullable enable
+ private class MyNullableModel
+ {
+ public string? Include { get; set; }
+
+ public string? Exclude { get; set; }
+ }
+#nullable restore
+
private class TryValidateModelModel
{
public int IntegerProperty { get; set; }