diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs
index 8850f96c6c..9109142b0a 100644
--- a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs
@@ -1,47 +1,99 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Microsoft.Framework.Internal;
+
namespace Microsoft.AspNet.Mvc.ModelBinding
{
///
/// Contains the result of model binding.
///
- public class ModelBindingResult
+ public struct ModelBindingResult : IEquatable
{
///
- /// Creates a new indicating a fatal error.
+ /// A representing the lack of a result. The model binding
+ /// system will continue to execute other model binders.
///
- /// The key using which was used to attempt binding the model.
- public ModelBindingResult(string key)
+ public static readonly ModelBindingResult NoResult = new ModelBindingResult();
+
+ ///
+ /// Returns a completed representing the lack of a result. The model
+ /// binding system will continue to execute other model binders.
+ ///
+ public static readonly Task NoResultAsync = Task.FromResult(NoResult);
+
+ ///
+ /// Creates a representing a failed model binding operation.
+ ///
+ /// The key of the current model binding operation.
+ /// A representing a failed model binding operation.
+ public static ModelBindingResult Failed([NotNull] string key)
+ {
+ return new ModelBindingResult(key, model: null, isModelSet: false, validationNode: null);
+ }
+
+ ///
+ /// Creates a completed representing a failed model binding operation.
+ ///
+ /// The key of the current model binding operation.
+ /// A completed representing a failed model binding operation.
+ public static Task FailedAsync([NotNull] string key)
+ {
+ return Task.FromResult(Failed(key));
+ }
+
+ ///
+ /// Creates a representing a successful model binding operation.
+ ///
+ /// The key of the current model binding operation.
+ /// The model value. May be null.
+ /// The . May be null.
+ /// A representing a successful model bind.
+ public static ModelBindingResult Success(
+ [NotNull] string key,
+ object model,
+ ModelValidationNode validationNode)
+ {
+ return new ModelBindingResult(key, model, isModelSet: true, validationNode: validationNode);
+ }
+
+ ///
+ /// Creates a completed representing a successful model binding
+ /// operation.
+ ///
+ /// The key of the current model binding operation.
+ /// The model value. May be null.
+ /// The . May be null.
+ /// A completed representing a successful model bind.
+ public static Task SuccessAsync(
+ [NotNull] string key,
+ object model,
+ ModelValidationNode validationNode)
+ {
+ return Task.FromResult(Success(key, model, validationNode));
+ }
+
+ ///
+ /// Creates a new using the provided
+ ///
+ /// The key of the current model binding operation.
+ /// The other to copy from.
+ public ModelBindingResult([NotNull] string key, ModelBindingResult other)
{
Key = key;
+
+ Model = other.Model;
+ IsModelSet = other.IsModelSet;
+ ValidationNode = other.ValidationNode;
}
- ///
- /// Creates a new .
- ///
- /// The model which was created by the .
- /// The key using which was used to attempt binding the model.
- /// A value that represents if the model has been set by the
- /// .
- public ModelBindingResult(object model, string key, bool isModelSet)
- : this(model, key, isModelSet, validationNode: null)
- {
- }
-
- ///
- /// Creates a new .
- ///
- /// The model which was created by the .
- /// The key using which was used to attempt binding the model.
- /// A value that represents if the model has been set by the
- /// .
- /// A which captures the validation information.
- ///
- public ModelBindingResult(object model, string key, bool isModelSet, ModelValidationNode validationNode)
+ private ModelBindingResult(string key, object model, bool isModelSet, ModelValidationNode validationNode)
{
+ Key = key;
Model = model;
- Key = key;
IsModelSet = isModelSet;
ValidationNode = validationNode;
}
@@ -76,5 +128,60 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// A associated with the current .
///
public ModelValidationNode ValidationNode { get; }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ var other = obj as ModelBindingResult?;
+ if (other == null)
+ {
+ return false;
+ }
+ else
+ {
+ return Equals(other.Value);
+ }
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ var hash = HashCodeCombiner.Start();
+ hash.Add(Key, StringComparer.OrdinalIgnoreCase);
+ hash.Add(IsModelSet);
+ hash.Add(Model);
+ return hash.CombinedHash;
+ }
+
+ ///
+ public bool Equals(ModelBindingResult other)
+ {
+ return
+ string.Equals(Key, other.Key, StringComparison.OrdinalIgnoreCase) &&
+ IsModelSet == other.IsModelSet &&
+ object.Equals(Model, other.Model);
+ }
+
+ ///
+ /// Compares objects for equality.
+ ///
+ /// A .
+ /// A .
+ /// true if the objects are equal, otherwise false.
+ public static bool operator ==(ModelBindingResult x, ModelBindingResult y)
+ {
+ return x.Equals(y);
+ }
+
+ ///
+ /// Compares objects for inequality.
+ ///
+ /// A .
+ /// A .
+ /// true if the objects are not equal, otherwise false.
+ public static bool operator !=(ModelBindingResult x, ModelBindingResult y)
+ {
+ return !x.Equals(y);
+ }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/project.json b/src/Microsoft.AspNet.Mvc.Abstractions/project.json
index f31e7850b9..8fb6eeb58f 100644
--- a/src/Microsoft.AspNet.Mvc.Abstractions/project.json
+++ b/src/Microsoft.AspNet.Mvc.Abstractions/project.json
@@ -10,12 +10,25 @@
},
"dependencies": {
"Microsoft.AspNet.Routing": "1.0.0-*",
- "Microsoft.Framework.CopyOnWriteDictionary.Sources": { "version": "1.0.0-*", "type": "build" },
- "Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" },
- "Microsoft.Framework.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" }
+ "Microsoft.Framework.CopyOnWriteDictionary.Sources": {
+ "version": "1.0.0-*",
+ "type": "build"
+ },
+ "Microsoft.Framework.HashCodeCombiner.Sources": {
+ "version": "1.0.0-*",
+ "type": "build"
+ },
+ "Microsoft.Framework.NotNullAttribute.Sources": {
+ "version": "1.0.0-*",
+ "type": "build"
+ },
+ "Microsoft.Framework.PropertyHelper.Sources": {
+ "version": "1.0.0-*",
+ "type": "build"
+ }
},
"frameworks": {
- "dnx451": {},
+ "dnx451": { },
"dnxcore50": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-beta-*",
diff --git a/src/Microsoft.AspNet.Mvc.Core/Actions/DefaultControllerActionArgumentBinder.cs b/src/Microsoft.AspNet.Mvc.Core/Actions/DefaultControllerActionArgumentBinder.cs
index c48230e017..f2650cc20f 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Actions/DefaultControllerActionArgumentBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Actions/DefaultControllerActionArgumentBinder.cs
@@ -81,8 +81,7 @@ namespace Microsoft.AspNet.Mvc.Actions
parameter.Name);
var modelBindingResult = await operationContext.ModelBinder.BindModelAsync(modelBindingContext);
- if (modelBindingResult != null &&
- modelBindingResult.IsModelSet &&
+ if (modelBindingResult.IsModelSet &&
modelBindingResult.ValidationNode != null)
{
var modelExplorer = new ModelExplorer(
@@ -180,7 +179,7 @@ namespace Microsoft.AspNet.Mvc.Actions
foreach (var parameter in parameterMetadata)
{
var modelBindingResult = await BindModelAsync(parameter, modelState, operationContext);
- if (modelBindingResult != null && modelBindingResult.IsModelSet)
+ if (modelBindingResult.IsModelSet)
{
arguments[parameter.Name] = modelBindingResult.Model;
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ArrayModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ArrayModelBinder.cs
index 4843261a2a..61b5e69fdc 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ArrayModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ArrayModelBinder.cs
@@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
if (bindingContext.ModelMetadata.IsReadOnly)
{
- return Task.FromResult(null);
+ return ModelBindingResult.NoResultAsync;
}
return base.BindModelAsync(bindingContext);
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BinderTypeBasedModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BinderTypeBasedModelBinder.cs
index cc458805ae..295d45b40f 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BinderTypeBasedModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BinderTypeBasedModelBinder.cs
@@ -25,9 +25,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
if (bindingContext.BinderType == null)
{
- // Return null so that we are able to continue with the default set of model binders,
+ // Return NoResult so that we are able to continue with the default set of model binders,
// if there is no specific model binder provided.
- return null;
+ return ModelBindingResult.NoResult;
}
var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices;
@@ -45,9 +45,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await modelBinder.BindModelAsync(bindingContext);
- var modelBindingResult = result != null ?
+ var modelBindingResult = result != ModelBindingResult.NoResult ?
result :
- new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ ModelBindingResult.Failed(bindingContext.ModelName);
// A model binder was specified by metadata and this binder handles all such cases.
// Always tell the model binding system to skip other model binders i.e. return non-null.
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BindingSourceModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BindingSourceModelBinder.cs
index 440a202002..bc2b464ef2 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BindingSourceModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BindingSourceModelBinder.cs
@@ -74,14 +74,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Binding Sources are opt-in. This model either didn't specify one or specified something
// incompatible so let other binders run.
- return null;
+ return ModelBindingResult.NoResult;
}
var result = await BindModelCoreAsync(context);
- var modelBindingResult = result != null ?
+ var modelBindingResult = result != ModelBindingResult.NoResult ?
result :
- new ModelBindingResult(model: null, key: context.ModelName, isModelSet: false);
+ ModelBindingResult.Failed(context.ModelName);
// This model binder is the only handler for its binding source.
// Always tell the model binding system to skip other model binders i.e. return non-null.
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
index c29cc298be..68c9c9a065 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
@@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// This model binder is the only handler for the Body binding source and it cannot run twice. Always
// tell the model binding system to skip other model binders and never to fall back i.e. indicate a
// fatal error.
- return new ModelBindingResult(modelBindingKey);
+ return ModelBindingResult.Failed(modelBindingKey);
}
try
@@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Formatter added an error. Do not use the model it returned. As above, tell the model binding
// system to skip other model binders and never to fall back.
- return new ModelBindingResult(modelBindingKey);
+ return ModelBindingResult.Failed(modelBindingKey);
}
var validationNode = new ModelValidationNode(modelBindingKey, bindingContext.ModelMetadata, model)
@@ -73,11 +73,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ValidateAllProperties = true
};
- return new ModelBindingResult(
- model,
- key: modelBindingKey,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(modelBindingKey, model, validationNode);
}
catch (Exception ex)
{
@@ -86,7 +82,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// This model binder is the only handler for the Body binding source and it cannot run twice. Always
// tell the model binding system to skip other model binders and never to fall back i.e. indicate a
// fatal error.
- return new ModelBindingResult(modelBindingKey);
+ return ModelBindingResult.Failed(modelBindingKey);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
index c1cd683223..1348855f74 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
@@ -23,14 +23,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Check if this binder applies.
if (bindingContext.ModelType != typeof(byte[]))
{
- return null;
+ return ModelBindingResult.NoResult;
}
// Check for missing data case 1: There was no element containing this data.
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
- return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
@@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var value = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(value))
{
- return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
try
@@ -50,11 +50,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelMetadata,
model);
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
}
catch (Exception ex)
{
@@ -63,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Matched the type (byte[]) only this binder supports. As in missing data cases, always tell the model
// binding system to skip other model binders i.e. return non-null.
- return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CancellationTokenModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CancellationTokenModelBinder.cs
index 534bc53a20..0ebdb0ca7c 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CancellationTokenModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CancellationTokenModelBinder.cs
@@ -23,14 +23,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
SuppressValidation = true,
};
- return Task.FromResult(new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode));
+ return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model, validationNode);
}
- return Task.FromResult(null);
+ return ModelBindingResult.NoResultAsync;
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CollectionModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CollectionModelBinder.cs
index 60f6a6131e..2582f954d1 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CollectionModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CollectionModelBinder.cs
@@ -43,14 +43,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelMetadata,
model);
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
}
- return null;
+ return ModelBindingResult.NoResult;
}
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
@@ -85,11 +81,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
valueProviderResult);
}
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: result.ValidationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, result.ValidationNode);
}
///
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs
index 93b2cff5e8..1156585055 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs
@@ -38,14 +38,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
if (newBindingContext == null)
{
// Unable to find a value provider for this binding source. Binding will fail.
- return null;
+ return ModelBindingResult.NoResult;
}
var modelBindingResult = await RunModelBinders(newBindingContext);
- if (modelBindingResult == null)
+ if (modelBindingResult == ModelBindingResult.NoResult)
{
// Unable to bind or something went wrong.
- return null;
+ return ModelBindingResult.NoResult;
}
var bindingKey = bindingContext.ModelName;
@@ -76,11 +76,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
- return new ModelBindingResult(
- modelBindingResult.Model,
- bindingKey,
- modelBindingResult.IsModelSet,
- modelBindingResult.ValidationNode);
+ return new ModelBindingResult(bindingKey, modelBindingResult);
}
private async Task RunModelBinders(ModelBindingContext bindingContext)
@@ -90,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
foreach (var binder in ModelBinders)
{
var result = await binder.BindModelAsync(bindingContext);
- if (result != null)
+ if (result != ModelBindingResult.NoResult)
{
// This condition is necessary because the ModelState entry would never be validated if
// caller fell back to the empty prefix, leading to an possibly-incorrect !IsValid. In most
@@ -110,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
// Either we couldn't find a binder, or the binder couldn't bind. Distinction is not important.
- return null;
+ return ModelBindingResult.NoResult;
}
private static ModelBindingContext CreateNewBindingContext(ModelBindingContext oldBindingContext)
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/DictionaryModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/DictionaryModelBinder.cs
index 85f229eb71..28043fdcf6 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/DictionaryModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/DictionaryModelBinder.cs
@@ -78,8 +78,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueResult = await modelBinder.BindModelAsync(valueBindingContext);
// Always add an entry to the dictionary but validate only if binding was successful.
- model[convertedKey] = ModelBindingHelper.CastOrDefault(valueResult?.Model);
- if (valueResult != null && valueResult.IsModelSet)
+ model[convertedKey] = ModelBindingHelper.CastOrDefault(valueResult.Model);
+ if (valueResult.IsModelSet)
{
validationNode.ChildNodes.Add(valueResult.ValidationNode);
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormCollectionModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormCollectionModelBinder.cs
index 7135bd52d2..97d7ccc934 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormCollectionModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormCollectionModelBinder.cs
@@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
if (bindingContext.ModelType != typeof(IFormCollection))
{
- return null;
+ return ModelBindingResult.NoResult;
}
object model;
@@ -43,11 +43,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
SuppressValidation = true,
};
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
}
private class EmptyFormCollection : IFormCollection
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormFileModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormFileModelBinder.cs
index 119147d89f..914678f710 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormFileModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/FormFileModelBinder.cs
@@ -36,13 +36,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
else
{
// This binder does not support the requested type.
- return null;
+ return ModelBindingResult.NoResult;
}
-
- ModelValidationNode validationNode = null;
- if (value != null)
+
+ if (value == null)
{
- validationNode =
+ return ModelBindingResult.Failed(bindingContext.ModelName);
+ }
+ else
+ {
+ var validationNode =
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value)
{
SuppressValidation = true,
@@ -52,13 +55,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
rawValue: null,
attemptedValue: null);
- }
- return new ModelBindingResult(
- value,
- bindingContext.ModelName,
- isModelSet: value != null,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, value, validationNode);
+ }
}
private async Task> GetFormFilesAsync(ModelBindingContext bindingContext)
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/GenericModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/GenericModelBinder.cs
index 7c8dcc2dbc..36cc3097a1 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/GenericModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/GenericModelBinder.cs
@@ -27,20 +27,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
!collectionBinder.CanCreateInstance(bindingContext.ModelType))
{
// Able to resolve a binder type but need a new model instance and that binder cannot create it.
- return null;
+ return ModelBindingResult.NoResult;
}
var result = await binder.BindModelAsync(bindingContext);
- var modelBindingResult = result != null ?
+ var modelBindingResult = result != ModelBindingResult.NoResult ?
result :
- new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ ModelBindingResult.Failed(bindingContext.ModelName);
// Were able to resolve a binder type.
- // Always tell the model binding system to skip other model binders i.e. return non-null.
+ // Always tell the model binding system to skip other model binders.
return modelBindingResult;
}
- return null;
+ return ModelBindingResult.NoResult;
}
private static Type ResolveBinderType(ModelBindingContext context)
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/HeaderModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/HeaderModelBinder.cs
index 21cd423056..ec7d2deb64 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/HeaderModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/HeaderModelBinder.cs
@@ -53,10 +53,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
- ModelValidationNode validationNode = null;
- if (model != null)
+ if (model == null)
{
- validationNode = new ModelValidationNode(
+ return ModelBindingResult.FailedAsync(bindingContext.ModelName);
+ }
+ else
+ {
+ var validationNode = new ModelValidationNode(
bindingContext.ModelName,
bindingContext.ModelMetadata,
model);
@@ -65,14 +68,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
request.Headers.GetCommaSeparatedValues(headerName),
request.Headers[headerName]);
- }
- return Task.FromResult(
- new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: model != null,
- validationNode: validationNode));
+ return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model, validationNode);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/KeyValuePairModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/KeyValuePairModelBinder.cs
index acaf075d0f..7d11b6eb28 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/KeyValuePairModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/KeyValuePairModelBinder.cs
@@ -32,13 +32,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelMetadata,
model,
childNodes);
-
- // Success
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: modelValidationNode);
+
+ return ModelBindingResult.Success(bindingContext.ModelName, model, modelValidationNode);
}
else if (!keyResult.IsModelSet && valueResult.IsModelSet)
{
@@ -47,8 +42,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Resources.KeyValuePair_BothKeyAndValueMustBePresent);
// Were able to get some data for this model.
- // Always tell the model binding system to skip other model binders i.e. return non-null.
- return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ // Always tell the model binding system to skip other model binders.
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
else if (keyResult.IsModelSet && !valueResult.IsModelSet)
{
@@ -57,8 +52,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Resources.KeyValuePair_BothKeyAndValueMustBePresent);
// Were able to get some data for this model.
- // Always tell the model binding system to skip other model binders i.e. return non-null.
- return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
+ // Always tell the model binding system to skip other model binders.
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
else
{
@@ -73,14 +68,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelMetadata,
model);
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
}
- return null;
+ return ModelBindingResult.NoResult;
}
}
@@ -102,7 +93,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var modelBindingResult = await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync(
propertyBindingContext);
- if (modelBindingResult != null)
+ if (modelBindingResult != ModelBindingResult.NoResult)
{
if (modelBindingResult.ValidationNode != null)
{
@@ -112,8 +103,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return modelBindingResult;
}
- // Always return a ModelBindingResult to avoid an NRE in BindModelAsync.
- return new ModelBindingResult(model: default(TModel), key: propertyModelName, isModelSet: false);
+ return ModelBindingResult.Failed(propertyModelName);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
index 484c04d9d5..a662a7eb6e 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
@@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelBindingHelper.ValidateBindingContext(bindingContext);
if (!CanBindType(bindingContext.ModelMetadata))
{
- return null;
+ return ModelBindingResult.NoResult;
}
var mutableObjectBinderContext = new MutableObjectBinderContext()
@@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
if (!(CanCreateModel(mutableObjectBinderContext)))
{
- return null;
+ return ModelBindingResult.NoResult;
}
// Create model first (if necessary) to avoid reporting errors about properties when activation fails.
@@ -54,11 +54,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.Model = model;
ProcessResults(bindingContext, results, validationNode);
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
}
///
@@ -301,10 +297,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
model: model);
var result = await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyContext);
- if (result == null)
+ if (result == ModelBindingResult.NoResult)
{
// Could not bind. Let ProcessResult() know explicitly.
- result = new ModelBindingResult(model: null, key: propertyContext.ModelName, isModelSet: false);
+ result = ModelBindingResult.Failed(propertyContext.ModelName);
}
results[propertyMetadata] = result;
@@ -424,9 +420,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// exceptions as necessary.
foreach (var entry in results)
{
- var result = entry.Value;
- if (result != null)
+ if (entry.Value != ModelBindingResult.NoResult)
{
+ var result = entry.Value;
var propertyMetadata = entry.Key;
SetProperty(bindingContext, modelExplorer, propertyMetadata, result);
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ServicesModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ServicesModelBinder.cs
index 69d3ae1e1c..f0071b876d 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ServicesModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ServicesModelBinder.cs
@@ -32,11 +32,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
SuppressValidation = true
};
- return Task.FromResult(new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode));
+ return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model, validationNode);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
index 6a96ec335c..89f1fd09de 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
@@ -19,14 +19,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
if (bindingContext.ModelMetadata.IsComplexType)
{
// this type cannot be converted
- return null;
+ return ModelBindingResult.NoResult;
}
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
// no entry
- return null;
+ return ModelBindingResult.NoResult;
}
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
@@ -45,8 +45,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
- var isModelSet = true;
-
// When converting newModel a null value may indicate a failed conversion for an otherwise required
// model (can't set a ValueType to null). This detects if a null model value is acceptable given the
// current bindingContext. If not, an error is logged.
@@ -56,31 +54,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
Resources.FormatCommon_ValueNotValidForProperty(model));
- isModelSet = false;
+ return ModelBindingResult.Failed(bindingContext.ModelName);
}
+ else
+ {
+ var validationNode = new ModelValidationNode(
+ bindingContext.ModelName,
+ bindingContext.ModelMetadata,
+ model);
- // Include a ModelValidationNode if binding succeeded.
- var validationNode = isModelSet ?
- new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model) :
- null;
-
- return new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet,
- validationNode);
+ return ModelBindingResult.Success(bindingContext.ModelName, model, validationNode);
+ }
}
catch (Exception ex)
{
bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex);
- }
- // Were able to find a converter for the type but conversion failed.
- // Tell the model binding system to skip other model binders i.e. return non-null.
- return new ModelBindingResult(
- model: null,
- key: bindingContext.ModelName,
- isModelSet: false);
+ // Were able to find a converter for the type but conversion failed.
+ // Tell the model binding system to skip other model binders.
+ return ModelBindingResult.Failed(bindingContext.ModelName);
+ }
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBindingHelper.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBindingHelper.cs
index efd271518f..321588a5ae 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBindingHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBindingHelper.cs
@@ -308,7 +308,7 @@ namespace Microsoft.AspNet.Mvc
modelBindingContext.PropertyFilter = predicate;
var modelBindingResult = await modelBinder.BindModelAsync(modelBindingContext);
- if (modelBindingResult != null && modelBindingResult.IsModelSet)
+ if (modelBindingResult.IsModelSet)
{
var modelExplorer = new ModelExplorer(metadataProvider, modelMetadata, modelBindingResult.Model);
var modelValidationContext = new ModelValidationContext(modelBindingContext, modelExplorer);
diff --git a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
index ef22afbae6..0c638352a2 100644
--- a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
@@ -24,14 +24,10 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
SuppressValidation = true,
};
- return Task.FromResult(new ModelBindingResult(
- model,
- bindingContext.ModelName,
- isModelSet: true,
- validationNode: validationNode));
+ return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model, validationNode);
}
- return Task.FromResult(null);
+ return ModelBindingResult.NoResultAsync;
}
}
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionArgumentBinderTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionArgumentBinderTests.cs
index 73276d9bb8..15a09c1a24 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionArgumentBinderTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionArgumentBinderTests.cs
@@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.Actions
{
Name = "foo",
ParameterType = typeof(object),
- BindingInfo = new BindingInfo(),
+ BindingInfo = new BindingInfo(),
});
var actionContext = GetActionContext(actionDescriptor);
@@ -34,7 +34,7 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(result: null));
+ .Returns(ModelBindingResult.NoResultAsync);
var actionBindingContext = new ActionBindingContext()
{
ModelBinder = binder.Object,
@@ -61,13 +61,13 @@ namespace Microsoft.AspNet.Mvc.Actions
{
Name = "foo",
ParameterType = typeof(object),
- BindingInfo = new BindingInfo(),
+ BindingInfo = new BindingInfo(),
});
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(new ModelBindingResult(null, "", false)));
+ .Returns(ModelBindingResult.FailedAsync(string.Empty));
var actionContext = new ActionContext(
new DefaultHttpContext(),
@@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.Actions
{
Name = "foo",
ParameterType = typeof(string),
- BindingInfo = new BindingInfo(),
+ BindingInfo = new BindingInfo(),
});
var value = "Hello world";
@@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.Actions
{
context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(string));
})
- .Returns(Task.FromResult(result: new ModelBindingResult(value, key: string.Empty, isModelSet: true)));
+ .Returns(ModelBindingResult.SuccessAsync(string.Empty, value, validationNode: null));
var actionContext = new ActionContext(
new DefaultHttpContext(),
@@ -178,7 +178,7 @@ namespace Microsoft.AspNet.Mvc.Actions
{
Name = "foo",
ParameterType = typeof(object),
- BindingInfo = new BindingInfo(),
+ BindingInfo = new BindingInfo(),
});
var actionContext = new ActionContext(
@@ -189,7 +189,7 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(null));
+ .Returns(ModelBindingResult.NoResultAsync);
var actionBindingContext = new ActionBindingContext()
{
@@ -263,7 +263,7 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(null));
+ .Returns(ModelBindingResult.NoResultAsync);
var actionBindingContext = new ActionBindingContext()
{
@@ -362,8 +362,8 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(
- result: new ModelBindingResult(model: null, key: string.Empty, isModelSet: isModelSet)));
+ .Returns(ModelBindingResult.SuccessAsync(string.Empty, model: null, validationNode: null));
+
var actionBindingContext = new ActionBindingContext()
{
ModelBinder = binder.Object,
@@ -400,8 +400,8 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder
.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(
- result: new ModelBindingResult(model: null, key: string.Empty, isModelSet: true)));
+ .Returns(ModelBindingResult.SuccessAsync(key: string.Empty, model: null, validationNode: null));
+
var actionBindingContext = new ActionBindingContext()
{
ModelBinder = binder.Object,
@@ -542,8 +542,14 @@ namespace Microsoft.AspNet.Mvc.Actions
.Returns(bindingContext =>
{
object model;
- var isModelSet = inputPropertyValues.TryGetValue(bindingContext.ModelName, out model);
- return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet));
+ if (inputPropertyValues.TryGetValue(bindingContext.ModelName, out model))
+ {
+ return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model, validationNode: null);
+ }
+ else
+ {
+ return ModelBindingResult.FailedAsync(bindingContext.ModelName);
+ }
});
var actionBindingContext = new ActionBindingContext
{
@@ -564,10 +570,10 @@ namespace Microsoft.AspNet.Mvc.Actions
private static ActionContext GetActionContext(ActionDescriptor descriptor = null)
{
- return new ActionContext(
- new DefaultHttpContext(),
- new RouteData(),
- descriptor ?? GetActionDescriptor());
+ return new ActionContext(
+ new DefaultHttpContext(),
+ new RouteData(),
+ descriptor ?? GetActionDescriptor());
}
private static ActionDescriptor GetActionDescriptor()
@@ -594,8 +600,7 @@ namespace Microsoft.AspNet.Mvc.Actions
.Returns(mbc =>
{
var validationNode = new ModelValidationNode(string.Empty, mbc.ModelMetadata, model);
- return Task.FromResult(
- result: new ModelBindingResult(model, string.Empty, isModelSet: true, validationNode: validationNode));
+ return ModelBindingResult.SuccessAsync(string.Empty, model, validationNode: validationNode);
});
return new ActionBindingContext()
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionInvokerTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionInvokerTest.cs
index 1f73ddd3e3..3e2a838cf1 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionInvokerTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Actions/ControllerActionInvokerTest.cs
@@ -2078,7 +2078,7 @@ namespace Microsoft.AspNet.Mvc.Actions
var binder = new Mock();
binder.Setup(b => b.BindModelAsync(It.IsAny()))
- .Returns(Task.FromResult(result: null));
+ .Returns(ModelBindingResult.NoResultAsync);
var context = new Mock();
context.SetupGet(c => c.Items)
.Returns(new Dictionary