Reverting #1837 and add non-generic overloads for TryUpdateModel

This commit is contained in:
Kirthi Krishnamraju 2015-02-05 11:27:32 -08:00
parent 1cc9be5df7
commit f6e701b2b2
8 changed files with 621 additions and 9 deletions

View File

@ -1104,6 +1104,82 @@ namespace Microsoft.AspNet.Mvc
predicate);
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary>
/// <param name="model">The model instance to update.</param>
/// <param name="modelType">The type of model instance to update.</param>
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>
/// </param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction]
public virtual async Task<bool> TryUpdateModelAsync([NotNull] object model,
[NotNull] Type modelType,
string prefix)
{
if (BindingContext == null)
{
var message = Resources.FormatPropertyOfTypeCannotBeNull(
nameof(BindingContext),
typeof(Controller).FullName);
throw new InvalidOperationException(message);
}
return await ModelBindingHelper.TryUpdateModelAsync(
model,
modelType,
prefix,
ActionContext.HttpContext,
ModelState,
MetadataProvider,
BindingContext.ModelBinder,
BindingContext.ValueProvider,
ObjectValidator,
BindingContext.ValidatorProvider);
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>.
/// </summary>
/// <param name="model">The model instance to update.</param>
/// <param name="modelType">The type of model instance to update.</param>
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>
/// </param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// <param name="predicate">A predicate which can be used to filter properties at runtime.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction]
public async Task<bool> TryUpdateModelAsync(
[NotNull] object model,
[NotNull] Type modelType,
string prefix,
[NotNull] IValueProvider valueProvider,
[NotNull] Func<ModelBindingContext, string, bool> predicate)
{
if (BindingContext == null)
{
var message = Resources.FormatPropertyOfTypeCannotBeNull(
nameof(BindingContext),
typeof(Controller).FullName);
throw new InvalidOperationException(message);
}
return await ModelBindingHelper.TryUpdateModelAsync(
model,
modelType,
prefix,
ActionContext.HttpContext,
ModelState,
MetadataProvider,
BindingContext.ModelBinder,
valueProvider,
ObjectValidator,
BindingContext.ValidatorProvider,
predicate);
}
/// <summary>
/// Validates the specified <paramref name="model"/> instance.
/// </summary>

View File

@ -128,14 +128,14 @@ namespace Microsoft.AspNet.Mvc
/// <param name="metadataProvider">The provider used for reading metadata for the model type.</param>
/// <param name="modelBinder">The <see cref="IModelBinder"/> used for binding.</param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// /// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
/// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
/// bound values.</param>
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
/// on the model instance.</param>
/// <param name="predicate">A predicate which can be used to
/// filter properties(for inclusion/exclusion) at runtime.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
public static async Task<bool> TryUpdateModelAsync<TModel>(
public static Task<bool> TryUpdateModelAsync<TModel>(
[NotNull] TModel model,
[NotNull] string prefix,
[NotNull] HttpContext httpContext,
@ -148,9 +148,113 @@ namespace Microsoft.AspNet.Mvc
[NotNull] Func<ModelBindingContext, string, bool> predicate)
where TModel : class
{
return TryUpdateModelAsync(
model,
typeof(TModel),
prefix,
httpContext,
modelState,
metadataProvider,
modelBinder,
valueProvider,
objectModelValidator,
validatorProvider,
predicate: predicate);
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the specified <paramref name="modelBinder"/>
/// and the specified <paramref name="valueProvider"/> and executes validation using the specified
/// <paramref name="validatorProvider"/>.
/// </summary>
/// <param name="model">The model instance to update and validate.</param>
/// <param name="modelType">The type of model instance to update and validate.</param>
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
/// </param>
/// <param name="httpContext">The <see cref="HttpContext"/> for the current executing request.</param>
/// <param name="modelState">The <see cref="ModelStateDictionary"/> used for maintaining state and
/// results of model-binding validation.</param>
/// <param name="metadataProvider">The provider used for reading metadata for the model type.</param>
/// <param name="modelBinder">The <see cref="IModelBinder"/> used for binding.</param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
/// bound values.</param>
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
/// on the model instance.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
public static Task<bool> TryUpdateModelAsync(
[NotNull] object model,
[NotNull] Type modelType,
[NotNull] string prefix,
[NotNull] HttpContext httpContext,
[NotNull] ModelStateDictionary modelState,
[NotNull] IModelMetadataProvider metadataProvider,
[NotNull] IModelBinder modelBinder,
[NotNull] IValueProvider valueProvider,
[NotNull] IObjectModelValidator objectModelValidator,
[NotNull] IModelValidatorProvider validatorProvider)
{
// Includes everything by default.
return TryUpdateModelAsync(
model,
modelType,
prefix,
httpContext,
modelState,
metadataProvider,
modelBinder,
valueProvider,
objectModelValidator,
validatorProvider,
predicate: (context, propertyName) => true);
}
/// <summary>
/// Updates the specified <paramref name="model"/> instance using the specified <paramref name="modelBinder"/>
/// and the specified <paramref name="valueProvider"/> and executes validation using the specified
/// <paramref name="validatorProvider"/>.
/// </summary>
/// <param name="model">The model instance to update and validate.</param>
/// <param name="modelType">The type of model instance to update and validate.</param>
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
/// </param>
/// <param name="httpContext">The <see cref="HttpContext"/> for the current executing request.</param>
/// <param name="modelState">The <see cref="ModelStateDictionary"/> used for maintaining state and
/// results of model-binding validation.</param>
/// <param name="metadataProvider">The provider used for reading metadata for the model type.</param>
/// <param name="modelBinder">The <see cref="IModelBinder"/> used for binding.</param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
/// bound values.</param>
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
/// on the model instance.</param>
/// <param name="predicate">A predicate which can be used to
/// filter properties(for inclusion/exclusion) at runtime.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
public static async Task<bool> TryUpdateModelAsync(
[NotNull] object model,
[NotNull] Type modelType,
[NotNull] string prefix,
[NotNull] HttpContext httpContext,
[NotNull] ModelStateDictionary modelState,
[NotNull] IModelMetadataProvider metadataProvider,
[NotNull] IModelBinder modelBinder,
[NotNull] IValueProvider valueProvider,
[NotNull] IObjectModelValidator objectModelValidator,
[NotNull] IModelValidatorProvider validatorProvider,
[NotNull] Func<ModelBindingContext, string, bool> predicate)
{
if (!modelType.IsAssignableFrom(model.GetType()))
{
var message = Resources.FormatModelType_WrongType(
model.GetType().FullName,
modelType.FullName);
throw new ArgumentException(message, nameof(modelType));
}
var modelMetadata = metadataProvider.GetMetadataForType(
modelAccessor: () => model,
modelType: model.GetType());
modelType: modelType);
var operationBindingContext = new OperationBindingContext
{

View File

@ -1706,6 +1706,14 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("CacheProfileNotFound"), p0);
}
/// <summary>
/// The model type '{0}' does not match the '{1}' type parameter.
/// </summary>
internal static string FormatModelType_WrongType(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ModelType_WrongType"), p0, p1);
}
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

View File

@ -445,4 +445,7 @@
<data name="CacheProfileNotFound" xml:space="preserve">
<value>The '{0}' cache profile is not defined.</value>
</data>
<data name="ModelType_WrongType" xml:space="preserve">
<value>The model's runtime type '{0}' is not assignable to the type '{1}'.</value>
</data>
</root>

View File

@ -1140,6 +1140,110 @@ namespace Microsoft.AspNet.Mvc.Test
binder.Verify();
}
[Fact]
public async Task TryUpdateModelNonGeneric_PredicateWithValueProviderOverload_UsesPassedArguments()
{
// Arrange
var modelName = "mymodel";
Func<ModelBindingContext, string, bool> includePredicate =
(context, propertyName) => string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
var binder = new Mock<IModelBinder>();
var valueProvider = Mock.Of<IValueProvider>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Callback((ModelBindingContext context) =>
{
Assert.Equal(modelName, context.ModelName);
Assert.Same(valueProvider, context.ValueProvider);
Assert.True(context.PropertyFilter(context, "include1"));
Assert.True(context.PropertyFilter(context, "include2"));
Assert.False(context.PropertyFilter(context, "exclude1"));
Assert.False(context.PropertyFilter(context, "exclude2"));
})
.Returns(Task.FromResult<ModelBindingResult>(null))
.Verifiable();
var controller = GetController(binder.Object, provider: null);
var model = new MyModel();
// Act
await controller.TryUpdateModelAsync(model, model.GetType(), modelName, valueProvider, includePredicate);
// Assert
binder.Verify();
}
[Fact]
public async Task TryUpdateModelNonGeneric_ModelTypeOverload_UsesPassedArguments()
{
// Arrange
var modelName = "mymodel";
var metadataProvider = new DataAnnotationsModelMetadataProvider();
var valueProvider = Mock.Of<IValueProvider>();
var binder = new Mock<IModelBinder>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Callback((ModelBindingContext context) =>
{
Assert.Equal(modelName, context.ModelName);
Assert.Same(valueProvider, context.ValueProvider);
// Include and exclude should be null, resulting in property
// being included.
Assert.True(context.PropertyFilter(context, "Property1"));
Assert.True(context.PropertyFilter(context, "Property2"));
})
.Returns(Task.FromResult<ModelBindingResult>(null))
.Verifiable();
var controller = GetController(binder.Object, valueProvider);
var model = new MyModel();
// Act
var result = await controller.TryUpdateModelAsync(model, model.GetType(), modelName);
// Assert
binder.Verify();
}
[Fact]
public async Task TryUpdateModelNonGeneric_BindToBaseDeclaredType_ModelTypeOverload()
{
// Arrange
var modelName = "mymodel";
var metadataProvider = new DataAnnotationsModelMetadataProvider();
var valueProvider = Mock.Of<IValueProvider>();
var binder = new Mock<IModelBinder>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Callback((ModelBindingContext context) =>
{
Assert.Equal(modelName, context.ModelName);
Assert.Same(valueProvider, context.ValueProvider);
// Include and exclude should be null, resulting in property
// being included.
Assert.True(context.PropertyFilter(context, "Property1"));
Assert.True(context.PropertyFilter(context, "Property2"));
})
.Returns(Task.FromResult<ModelBindingResult>(null))
.Verifiable();
var controller = GetController(binder.Object, valueProvider);
MyModel model = new MyDerivedModel();
// Act
var result = await controller.TryUpdateModelAsync(model, model.GetType(), modelName);
// Assert
binder.Verify();
}
#endif
[Fact]
@ -1366,6 +1470,11 @@ namespace Microsoft.AspNet.Mvc.Test
public string Property2 { get; set; }
}
private class MyDerivedModel : MyModel
{
public string Property3 { get; set; }
}
private class User
{
public User(int id)

View File

@ -479,6 +479,222 @@ namespace Microsoft.AspNet.Mvc.Core.Test
ex.Message);
}
[Fact]
public async Task TryUpdateModelNonGeneric_PredicateOverload_ReturnsFalse_IfBinderReturnsFalse()
{
// Arrange
var metadataProvider = new Mock<IModelMetadataProvider>();
metadataProvider.Setup(m => m.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Returns(new ModelMetadata(metadataProvider.Object, null, null, typeof(MyModel), null))
.Verifiable();
var binder = new Mock<IModelBinder>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(Task.FromResult<ModelBindingResult>(null));
var model = new MyModel();
Func<ModelBindingContext, string, bool> includePredicate =
(context, propertyName) => true;
// Act
var result = await ModelBindingHelper.TryUpdateModelAsync(
model,
model.GetType(),
prefix: null,
httpContext: Mock.Of<HttpContext>(),
modelState: new ModelStateDictionary(),
metadataProvider: metadataProvider.Object,
modelBinder: GetCompositeBinder(binder.Object),
valueProvider: Mock.Of<IValueProvider>(),
objectModelValidator: Mock.Of<IObjectModelValidator>(),
validatorProvider: Mock.Of<IModelValidatorProvider>(),
predicate: includePredicate);
// Assert
Assert.False(result);
Assert.Null(model.MyProperty);
Assert.Null(model.IncludedProperty);
Assert.Null(model.ExcludedProperty);
metadataProvider.Verify();
}
[Fact]
public async Task TryUpdateModelNonGeneric_PredicateOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully()
{
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new ComplexModelDtoModelBinder(),
new MutableObjectModelBinder()
};
var validator = new DataAnnotationsModelValidatorProvider();
var model = new MyModel
{
MyProperty = "Old-Value",
IncludedProperty = "Old-IncludedPropertyValue",
ExcludedProperty = "Old-ExcludedPropertyValue"
};
var modelStateDictionary = new ModelStateDictionary();
var values = new Dictionary<string, object>
{
{ "", null },
{ "MyProperty", "MyPropertyValue" },
{ "IncludedProperty", "IncludedPropertyValue" },
{ "ExcludedProperty", "ExcludedPropertyValue" }
};
Func<ModelBindingContext, string, bool> includePredicate =
(context, propertyName) =>
string.Equals(propertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) ||
string.Equals(propertyName, "MyProperty", StringComparison.OrdinalIgnoreCase);
var valueProvider = new TestValueProvider(values);
var metadataProvider = new DataAnnotationsModelMetadataProvider();
// Act
var result = await ModelBindingHelper.TryUpdateModelAsync(
model,
model.GetType(),
"",
Mock.Of<HttpContext>(),
modelStateDictionary,
metadataProvider,
GetCompositeBinder(binders),
valueProvider,
new DefaultObjectValidator(
Mock.Of<IValidationExcludeFiltersProvider>(),
metadataProvider),
validator,
includePredicate);
// Assert
Assert.True(result);
Assert.Equal("MyPropertyValue", model.MyProperty);
Assert.Equal("IncludedPropertyValue", model.IncludedProperty);
Assert.Equal("Old-ExcludedPropertyValue", model.ExcludedProperty);
}
[Fact]
public async Task TryUpdateModelNonGeneric_ModelTypeOverload_ReturnsFalse_IfBinderReturnsFalse()
{
// Arrange
var metadataProvider = new Mock<IModelMetadataProvider>();
metadataProvider.Setup(m => m.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Returns(new ModelMetadata(metadataProvider.Object, null, null, typeof(MyModel), null))
.Verifiable();
var binder = new Mock<IModelBinder>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(Task.FromResult<ModelBindingResult>(null));
var model = new MyModel();
// Act
var result = await ModelBindingHelper.TryUpdateModelAsync(
model,
modelType: model.GetType(),
prefix: null,
httpContext: Mock.Of<HttpContext>(),
modelState: new ModelStateDictionary(),
metadataProvider: metadataProvider.Object,
modelBinder: GetCompositeBinder(binder.Object),
valueProvider: Mock.Of<IValueProvider>(),
objectModelValidator: Mock.Of<IObjectModelValidator>(),
validatorProvider: Mock.Of<IModelValidatorProvider>());
// Assert
Assert.False(result);
Assert.Null(model.MyProperty);
metadataProvider.Verify();
}
[Fact]
public async Task TryUpdateModelNonGeneric_ModelTypeOverload_ReturnsTrue_IfModelBindsAndValidatesSuccessfully()
{
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new ComplexModelDtoModelBinder(),
new MutableObjectModelBinder()
};
var validator = new DataAnnotationsModelValidatorProvider();
var model = new MyModel { MyProperty = "Old-Value" };
var modelStateDictionary = new ModelStateDictionary();
var values = new Dictionary<string, object>
{
{ "", null },
{ "MyProperty", "MyPropertyValue" }
};
var valueProvider = new TestValueProvider(values);
var metadataProvider = new DataAnnotationsModelMetadataProvider();
// Act
var result = await ModelBindingHelper.TryUpdateModelAsync(
model,
model.GetType(),
"",
Mock.Of<HttpContext>(),
modelStateDictionary,
new DataAnnotationsModelMetadataProvider(),
GetCompositeBinder(binders),
valueProvider,
new DefaultObjectValidator(
Mock.Of<IValidationExcludeFiltersProvider>(),
metadataProvider),
validator);
// Assert
Assert.True(result);
Assert.Equal("MyPropertyValue", model.MyProperty);
}
[Fact]
public async Task TryUpdataModel_ModelTypeDifferentFromModel_Throws()
{
// Arrange
var metadataProvider = new Mock<IModelMetadataProvider>();
metadataProvider.Setup(m => m.GetMetadataForType(null, It.IsAny<Type>()))
.Returns(new ModelMetadata(metadataProvider.Object,
containerType: null,
modelAccessor: null,
modelType: typeof(MyModel),
propertyName: null))
.Verifiable();
var binder = new Mock<IModelBinder>();
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(Task.FromResult<ModelBindingResult>(null));
var model = new MyModel();
Func<ModelBindingContext, string, bool> includePredicate =
(context, propertyName) => true;
// Act & Assert
var exception = await Assert.ThrowsAsync<ArgumentException>(
() => ModelBindingHelper.TryUpdateModelAsync(
model,
typeof(User),
null,
Mock.Of<HttpContext>(),
new ModelStateDictionary(),
metadataProvider.Object,
GetCompositeBinder(binder.Object),
Mock.Of<IValueProvider>(),
new DefaultObjectValidator(
Mock.Of<IValidationExcludeFiltersProvider>(),
metadataProvider.Object),
Mock.Of<IModelValidatorProvider>(),
includePredicate));
var expectedMessage = string.Format("The model's runtime type '{0}' is not assignable to the type '{1}'." +
Environment.NewLine +
"Parameter name: modelType",
model.GetType().FullName,
typeof(User).FullName);
Assert.Equal(expectedMessage, exception.Message);
}
private static IModelBinder GetCompositeBinder(params IModelBinder[] binders)
{
return new CompositeModelBinder(binders);

View File

@ -398,7 +398,6 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal("WA_Query", user.ShippingAddress.State);
Assert.Equal(3, user.ShippingAddress.Street);
Assert.Equal(4, user.ShippingAddress.Zip);
}
[Fact]
@ -1573,6 +1572,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
[Fact]
public async Task ModelBinder_FormatsDontMatch_ThrowsUserFriendlyException()
{
// Arrange
var server = TestServer.Create(_services, _app);
@ -1644,6 +1644,29 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal(expectedDictionary, dictionary);
}
[Fact]
public async Task TryUpdateModelNonGeneric_IncludesAllProperties_CanBind()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// Act
var response = await client.GetStringAsync("http://localhost/TryUpdateModel/" +
"GetUserAsync_ModelType_IncludeAll" +
"?id=123&RegisterationMonth=March&Key=123&UserName=SomeName");
// Assert
var user = JsonConvert.DeserializeObject<User>(response);
// Should not update any not explicitly mentioned properties.
Assert.Equal("SomeName", user.UserName);
Assert.Equal(123, user.Key);
// Should Update all included properties.
Assert.Equal("March", user.RegisterationMonth);
}
[Fact]
public async Task FormCollectionModelBinder_CanBind_FormValues()
{
@ -1731,5 +1754,28 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var fileContent = await response.Content.ReadAsStringAsync();
Assert.Equal(expectedContent, fileContent);
}
[Fact]
public async Task TryUpdateModelNonGenericIncludesAllProperties_ByDefault()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// Act
var response = await client.GetStringAsync("http://localhost/TryUpdateModel/" +
"GetUserAsync_ModelType_IncludeAllByDefault" +
"?id=123&RegisterationMonth=March&Key=123&UserName=SomeName");
// Assert
var user = JsonConvert.DeserializeObject<User>(response);
// Should not update any not explicitly mentioned properties.
Assert.Equal("SomeName", user.UserName);
Assert.Equal(123, user.Key);
// Should Update all included properties.
Assert.Equal("March", user.RegisterationMonth);
}
}
}

View File

@ -2,9 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using System.Collections.Generic;
using Microsoft.AspNet.Http.Core.Collections;
using Microsoft.AspNet.Http;
namespace ModelBindingWebSite.Controllers
{
@ -100,12 +104,58 @@ namespace ModelBindingWebSite.Controllers
public async Task<Employee> GetEmployeeAsync_BindToBaseDeclaredType()
{
var employee = new Employee();
await TryUpdateModelAsync<Person>(
employee,
prefix: string.Empty);
var backingStore = new ReadableStringCollection(
new Dictionary<string, string[]>
{
{ "Parent.Name", new[] { "fatherName"} },
{ "Parent.Parent.Name", new[] {"grandFatherName" } },
{ "Department", new[] {"Sales" } }
});
return employee;
Person employee = new Employee();
await TryUpdateModelAsync(
employee,
employee.GetType(),
prefix: string.Empty,
valueProvider: new ReadableStringCollectionValueProvider(
BindingSource.Query,
backingStore,
CultureInfo.CurrentCulture),
predicate: (content, propertyName) => true);
return (Employee)employee;
}
public async Task<User> GetUserAsync_ModelType_IncludeAll(int id)
{
var backingStore = new ReadableStringCollection(
new Dictionary<string, string[]>
{
{ "Key", new[] { "123"} },
{ "RegisterationMonth", new[] {"March" } },
{ "UserName", new[] {"SomeName" } }
});
var user = GetUser(id);
await TryUpdateModelAsync(user,
typeof(User),
prefix: string.Empty,
valueProvider: new ReadableStringCollectionValueProvider(
BindingSource.Query,
backingStore,
CultureInfo.CurrentCulture),
predicate: (content, propertyName) => true);
return user;
}
public async Task<User> GetUserAsync_ModelType_IncludeAllByDefault(int id)
{
var user = GetUser(id);
await TryUpdateModelAsync(user, user.GetType(), prefix: string.Empty);
return user;
}
private User GetUser(int id)