Removing creating ModelValidationNode by default in CompositeModelBinder.
This moves the responsibility of of MVN creation to individual model binders if they want the individual models to be validated.
This commit is contained in:
parent
3fe0490b99
commit
4f419eee55
|
|
@ -89,12 +89,16 @@ namespace Microsoft.AspNet.Mvc
|
|||
metadata,
|
||||
modelBindingResult.Model);
|
||||
|
||||
var validationContext = new ModelValidationContext(
|
||||
modelBindingContext.BindingSource,
|
||||
operationContext.ValidatorProvider,
|
||||
modelState,
|
||||
modelExplorer);
|
||||
_validator.Validate(validationContext, modelBindingResult.ValidationNode);
|
||||
if (modelBindingResult.ValidationNode != null)
|
||||
{
|
||||
var validationContext = new ModelValidationContext(
|
||||
modelBindingContext.BindingSource,
|
||||
operationContext.ValidatorProvider,
|
||||
modelState,
|
||||
modelExplorer);
|
||||
|
||||
_validator.Validate(validationContext, modelBindingResult.ValidationNode);
|
||||
}
|
||||
}
|
||||
|
||||
return modelBindingResult;
|
||||
|
|
|
|||
|
|
@ -39,12 +39,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
try
|
||||
{
|
||||
var model = Convert.FromBase64String(value);
|
||||
var validationNode = new ModelValidationNode(
|
||||
bindingContext.ModelName,
|
||||
bindingContext.ModelMetadata,
|
||||
model);
|
||||
|
||||
// We do not need to set an explict ModelValidationNode since CompositeModelBinder does that automatically.
|
||||
return new ModelBindingResult(
|
||||
model,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: true);
|
||||
isModelSet: true,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
if (bindingContext.ModelType == typeof(CancellationToken))
|
||||
{
|
||||
var model = bindingContext.OperationBindingContext.HttpContext.RequestAborted;
|
||||
return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true));
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model);
|
||||
return Task.FromResult(new ModelBindingResult(
|
||||
model,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: true,
|
||||
validationNode: validationNode));
|
||||
}
|
||||
|
||||
return Task.FromResult<ModelBindingResult>(null);
|
||||
|
|
|
|||
|
|
@ -83,24 +83,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
|
||||
// Update the model validation node if the model binding result was set but no validation node was provided.
|
||||
// This would typically be the case where leaf level model binders, do not have to add a validation node
|
||||
// for validation to take effect. The composite being the entry point for model binders, takes care or
|
||||
// adding missing validation nodes.
|
||||
var modelValidationNode = modelBindingResult.ValidationNode;
|
||||
if (modelBindingResult.IsModelSet && modelValidationNode == null)
|
||||
{
|
||||
modelValidationNode = new ModelValidationNode(
|
||||
bindingKey,
|
||||
bindingContext.ModelMetadata,
|
||||
modelBindingResult.Model);
|
||||
}
|
||||
|
||||
return new ModelBindingResult(
|
||||
modelBindingResult.Model,
|
||||
bindingKey,
|
||||
modelBindingResult.IsModelSet,
|
||||
modelValidationNode);
|
||||
modelBindingResult.ValidationNode);
|
||||
}
|
||||
|
||||
private async Task<ModelBindingResult> TryBind(ModelBindingContext bindingContext)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
model = new FormCollection(new Dictionary<string, string[]>());
|
||||
}
|
||||
|
||||
return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true);
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model);
|
||||
return new ModelBindingResult(
|
||||
model,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: true,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,14 +24,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
var postedFiles = await GetFormFilesAsync(bindingContext);
|
||||
var value = postedFiles.FirstOrDefault();
|
||||
return new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null);
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
return new ModelBindingResult(
|
||||
value,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: value != null,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
else if (typeof(IEnumerable<IFormFile>).GetTypeInfo().IsAssignableFrom(
|
||||
bindingContext.ModelType.GetTypeInfo()))
|
||||
{
|
||||
var postedFiles = await GetFormFilesAsync(bindingContext);
|
||||
var value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
|
||||
return new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null);
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
return new ModelBindingResult(
|
||||
value,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: value != null,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -30,12 +30,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
|
||||
ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
|
||||
var validationNode = new ModelValidationNode(
|
||||
bindingContext.ModelName,
|
||||
bindingContext.ModelMetadata,
|
||||
newModel);
|
||||
|
||||
// We do not need to set an explict ModelValidationNode since CompositeModelBinder does that automatically.
|
||||
return new ModelBindingResult(
|
||||
newModel,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: true);
|
||||
isModelSet: true,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
|
||||
var model = valueProviderResult.RawValue;
|
||||
ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model);
|
||||
var validationNode = new ModelValidationNode(
|
||||
bindingContext.ModelName,
|
||||
bindingContext.ModelMetadata,
|
||||
model);
|
||||
|
||||
// We do not need to set an explict ModelValidationNode since CompositeModelBinder does that automatically.
|
||||
return new ModelBindingResult(
|
||||
model,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: true);
|
||||
isModelSet: true,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
|
||||
internal static async Task<ValueProviderResult> GetCompatibleValueProviderResult(ModelBindingContext context)
|
||||
|
|
|
|||
|
|
@ -247,8 +247,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
modelState.GetFieldValidationState(errorKey) == ModelValidationState.Unvalidated)
|
||||
{
|
||||
|
||||
// If we are not able to add a model error
|
||||
// for instance when the max error count is reached, mark the model as skipped.
|
||||
// If we are not able to add a model error
|
||||
// for instance when the max error count is reached, mark the model as skipped.
|
||||
modelState.MarkFieldSkipped(errorKey);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -309,7 +309,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
{
|
||||
if (mbc.ModelType == typeof(int))
|
||||
{
|
||||
return Task.FromResult(new ModelBindingResult(42, mbc.ModelName, true));
|
||||
var model = 42;
|
||||
var validationNode = new ModelValidationNode(mbc.ModelName, mbc.ModelMetadata, model);
|
||||
return Task.FromResult(new ModelBindingResult(model, mbc.ModelName, true, validationNode));
|
||||
}
|
||||
return Task.FromResult<ModelBindingResult>(null);
|
||||
});
|
||||
|
|
@ -325,7 +327,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
{
|
||||
if (mbc.ModelType == typeof(string))
|
||||
{
|
||||
return Task.FromResult(new ModelBindingResult("some-value", mbc.ModelName, true));
|
||||
var model = "some-value";
|
||||
var validationNode = new ModelValidationNode(mbc.ModelName, mbc.ModelMetadata, model);
|
||||
return Task.FromResult(new ModelBindingResult(model, mbc.ModelName, true, validationNode));
|
||||
}
|
||||
return Task.FromResult<ModelBindingResult>(null);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -588,10 +588,14 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
private static ActionBindingContext GetActionBindingContext(object model)
|
||||
{
|
||||
var binder = new Mock<IModelBinder>();
|
||||
binder
|
||||
.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Returns(Task.FromResult(
|
||||
result: new ModelBindingResult(model: model, key: string.Empty, isModelSet: true)));
|
||||
binder.Setup(b => b.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.Returns<ModelBindingContext>(mbc =>
|
||||
{
|
||||
var validationNode = new ModelValidationNode(string.Empty, mbc.ModelMetadata, model);
|
||||
return Task.FromResult(
|
||||
result: new ModelBindingResult(model, string.Empty, isModelSet: true, validationNode: validationNode));
|
||||
});
|
||||
|
||||
return new ActionBindingContext()
|
||||
{
|
||||
ModelBinder = binder.Object,
|
||||
|
|
|
|||
|
|
@ -1462,7 +1462,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
};
|
||||
var url = "http://localhost/dealers/43/update-vehicle?dealer.name=TestCarDealer&dealer.location=NE";
|
||||
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsJsonAsync(url, postedContent);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,9 @@ namespace ModelBindingWebSite.Controllers
|
|||
// by the type converter binder.
|
||||
OrderStatus model;
|
||||
var isModelSet = Enum.TryParse<OrderStatus>("Status" + request.Query.Get("status"), out model);
|
||||
return Task.FromResult(new ModelBindingResult(model, "status", isModelSet));
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model);
|
||||
return Task.FromResult(new ModelBindingResult(model, "status", isModelSet, validationNode));
|
||||
}
|
||||
|
||||
return Task.FromResult<ModelBindingResult>(null);
|
||||
|
|
@ -91,15 +93,17 @@ namespace ModelBindingWebSite.Controllers
|
|||
|
||||
model.BinderType = GetType();
|
||||
|
||||
var key =
|
||||
string.IsNullOrEmpty(bindingContext.ModelName) ?
|
||||
"productId" :
|
||||
var key =
|
||||
string.IsNullOrEmpty(bindingContext.ModelName) ?
|
||||
"productId" :
|
||||
bindingContext.ModelName + "." + "productId";
|
||||
|
||||
var value = await bindingContext.ValueProvider.GetValueAsync(key);
|
||||
model.ProductId = (int)value.ConvertTo(typeof(int));
|
||||
|
||||
return new ModelBindingResult(model, key, true);
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
return new ModelBindingResult(model, key, true, validationNode);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
Loading…
Reference in New Issue