diff --git a/samples/MvcSample/HomeController.cs b/samples/MvcSample/HomeController.cs
index db8481ef11..6843fdec4f 100644
--- a/samples/MvcSample/HomeController.cs
+++ b/samples/MvcSample/HomeController.cs
@@ -10,6 +10,22 @@ namespace MvcSample
return View("MyView", User());
}
+ ///
+ /// Action that exercises query\form based model binding.
+ ///
+ public IActionResult SaveUser(User user)
+ {
+ return View("MyView", user);
+ }
+
+ ///
+ /// Action that exercises input formatter
+ ///
+ public IActionResult Post([FromBody]User user)
+ {
+ return View("MyView", user);
+ }
+
public IActionResult Something()
{
return new ContentResult
diff --git a/samples/MvcSample/Startup.cs b/samples/MvcSample/Startup.cs
index d3f5adbe64..b01e7ee5b4 100644
--- a/samples/MvcSample/Startup.cs
+++ b/samples/MvcSample/Startup.cs
@@ -40,14 +40,16 @@ namespace MvcSample
var endpoint = ActivatorUtilities.CreateInstance(mvcServices.Services);
- router.Add(new TemplateRoute(
- endpoint,
- "{controller}/{action}",
- new Dictionary(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" }, { "action", "Index" } }));
router.Add(new TemplateRoute(
endpoint,
"{controller}",
new Dictionary(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" } }));
+
+ router.Add(new TemplateRoute(
+ endpoint,
+ "{controller}/{action}",
+ new Dictionary(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" }, { "action", "Index" } }));
+
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionInvokerProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ActionInvokerProvider.cs
index 7025a62901..d49f04c2f4 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ActionInvokerProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ActionInvokerProvider.cs
@@ -7,13 +7,16 @@ namespace Microsoft.AspNet.Mvc
private readonly IActionResultFactory _actionResultFactory;
private readonly IServiceProvider _serviceProvider;
private readonly IControllerFactory _controllerFactory;
+ private readonly IActionBindingContextProvider _bindingProvider;
public ActionInvokerProvider(IActionResultFactory actionResultFactory,
IControllerFactory controllerFactory,
+ IActionBindingContextProvider bindingProvider,
IServiceProvider serviceProvider)
{
_actionResultFactory = actionResultFactory;
_controllerFactory = controllerFactory;
+ _bindingProvider = bindingProvider;
_serviceProvider = serviceProvider;
}
@@ -24,21 +27,20 @@ namespace Microsoft.AspNet.Mvc
public void Invoke(ActionInvokerProviderContext context, Action callNext)
{
- var ad = context.ActionContext.ActionDescriptor as ReflectedActionDescriptor;
+ var actionDescriptor = context.ActionContext.ActionDescriptor as ReflectedActionDescriptor;
- if (ad != null)
+ if (actionDescriptor != null)
{
context.Result = new ReflectedActionInvoker(
- context.ActionContext,
- ad,
- _actionResultFactory,
- _controllerFactory,
- _serviceProvider);
+ context.ActionContext,
+ actionDescriptor,
+ _actionResultFactory,
+ _controllerFactory,
+ _bindingProvider,
+ _serviceProvider);
}
callNext();
}
-
-
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/BodyParameterInfo.cs b/src/Microsoft.AspNet.Mvc.Core/BodyParameterInfo.cs
new file mode 100644
index 0000000000..f05807f086
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/BodyParameterInfo.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Microsoft.AspNet.Mvc
+{
+ public class BodyParameterInfo
+ {
+ public BodyParameterInfo(Type parameterType)
+ {
+ ParameterType = parameterType;
+ }
+
+ public Type ParameterType { get; private set; }
+ }
+}
+
diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultActionSelector.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultActionSelector.cs
index 0a79115bcb..a04de05dfb 100644
--- a/src/Microsoft.AspNet.Mvc.Core/DefaultActionSelector.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/DefaultActionSelector.cs
@@ -3,21 +3,19 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection;
-using Microsoft.AspNet.Mvc.ModelBinding;
namespace Microsoft.AspNet.Mvc
{
public class DefaultActionSelector : IActionSelector
{
private readonly INestedProviderManager _actionDescriptorProvider;
- private readonly IEnumerable _valueProviderFactory;
+ private readonly IActionBindingContextProvider _bindingProvider;
- public DefaultActionSelector(
- INestedProviderManager actionDescriptorProvider,
- IEnumerable valueProviderFactories)
+ public DefaultActionSelector(INestedProviderManager actionDescriptorProvider,
+ IActionBindingContextProvider bindingProvider)
{
_actionDescriptorProvider = actionDescriptorProvider;
- _valueProviderFactory = valueProviderFactories;
+ _bindingProvider = bindingProvider;
}
public async Task SelectAsync(RequestContext context)
@@ -61,9 +59,6 @@ namespace Microsoft.AspNet.Mvc
protected virtual async Task SelectBestCandidate(RequestContext context, List candidates)
{
- var valueProviders = await Task.WhenAll(_valueProviderFactory.Select(vpf => vpf.GetValueProviderAsync(context)));
- valueProviders = valueProviders.Where(vp => vp != null).ToArray();
-
var applicableCandiates = new List();
foreach (var action in candidates)
{
@@ -72,18 +67,20 @@ namespace Microsoft.AspNet.Mvc
{
Action = action,
};
+ var actionContext = new ActionContext(context.HttpContext, context.RouteValues, action);
+ var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(actionContext);
- foreach (var parameter in action.Parameters.Where(p => !p.Binding.IsFromBody))
+ foreach (var parameter in action.Parameters.Where(p => p.ParameterBindingInfo != null))
{
- if (valueProviders.Any(vp => vp.ContainsPrefix(parameter.Binding.Prefix)))
+ if (actionBindingContext.ValueProvider.ContainsPrefix(parameter.ParameterBindingInfo.Prefix))
{
candidate.FoundParameters++;
- if (parameter.Binding.IsOptional)
+ if (parameter.IsOptional)
{
candidate.FoundOptionalParameters++;
}
}
- else if (!parameter.Binding.IsOptional)
+ else if (!parameter.IsOptional)
{
isApplicable = false;
break;
diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultParameterDescriptorFactory.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultParameterDescriptorFactory.cs
index 4bb1ec6b4a..a32167bcae 100644
--- a/src/Microsoft.AspNet.Mvc.Core/DefaultParameterDescriptorFactory.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/DefaultParameterDescriptorFactory.cs
@@ -1,5 +1,4 @@
-
-using System.Reflection;
+using System.Reflection;
namespace Microsoft.AspNet.Mvc
{
@@ -7,24 +6,29 @@ namespace Microsoft.AspNet.Mvc
{
public ParameterDescriptor GetDescriptor(ParameterInfo parameter)
{
- var bindingInfo = new ParameterBindingInfo()
- {
- IsOptional = parameter.IsOptional,
- IsFromBody = IsFromBody(parameter),
- Prefix = parameter.Name,
- };
+ bool isFromBody = IsFromBody(parameter);
- return new ParameterDescriptor()
+ return new ParameterDescriptor
{
Name = parameter.Name,
- Binding = bindingInfo,
+ IsOptional = parameter.IsOptional,
+ ParameterBindingInfo = isFromBody ? null : GetParameterBindingInfo(parameter),
+ BodyParameterInfo = isFromBody ? GetBodyParameterInfo(parameter) : null
};
}
-
public virtual bool IsFromBody(ParameterInfo parameter)
{
- // Assume for now everything is read from value providers
- return false;
+ return parameter.GetCustomAttribute() != null;
+ }
+
+ private ParameterBindingInfo GetParameterBindingInfo(ParameterInfo parameter)
+ {
+ return new ParameterBindingInfo(parameter.Name, parameter.ParameterType);
+ }
+
+ private BodyParameterInfo GetBodyParameterInfo(ParameterInfo parameter)
+ {
+ return new BodyParameterInfo(parameter.ParameterType);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Internal/ActionBindingContextExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/Internal/ActionBindingContextExtensions.cs
new file mode 100644
index 0000000000..9e311f0039
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Internal/ActionBindingContextExtensions.cs
@@ -0,0 +1,38 @@
+using Microsoft.AspNet.Mvc.ModelBinding;
+
+namespace Microsoft.AspNet.Mvc.Internal
+{
+ public static class ActionBindingContextExtensions
+ {
+ public static InputFormatterContext CreateInputFormatterContext(this ActionBindingContext actionBindingContext,
+ ModelStateDictionary modelState,
+ ParameterDescriptor parameter)
+ {
+ var metadataProvider = actionBindingContext.MetadataProvider;
+ var parameterType = parameter.BodyParameterInfo.ParameterType;
+ var modelMetadata = metadataProvider.GetMetadataForType(modelAccessor: null, modelType: parameterType);
+ return new InputFormatterContext(modelMetadata, modelState);
+ }
+
+ public static ModelBindingContext CreateModelBindingContext(this ActionBindingContext actionBindingContext,
+ ModelStateDictionary modelState,
+ ParameterDescriptor parameter)
+ {
+ var metadataProvider = actionBindingContext.MetadataProvider;
+ var parameterType = parameter.ParameterBindingInfo.ParameterType;
+ var modelMetadata = metadataProvider.GetMetadataForType(modelAccessor: null, modelType: parameterType);
+
+ return new ModelBindingContext
+ {
+ ModelName = parameter.Name,
+ ModelState = modelState,
+ ModelMetadata = modelMetadata,
+ ModelBinder = actionBindingContext.ModelBinder,
+ ValueProvider = actionBindingContext.ValueProvider,
+ MetadataProvider = metadataProvider,
+ HttpContext = actionBindingContext.ActionContext.HttpContext,
+ FallbackToEmptyPrefix = true
+ };
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/ActionBindingContext.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/ActionBindingContext.cs
new file mode 100644
index 0000000000..debc2a555e
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/ActionBindingContext.cs
@@ -0,0 +1,30 @@
+using Microsoft.AspNet.Mvc.ModelBinding;
+
+namespace Microsoft.AspNet.Mvc
+{
+ public class ActionBindingContext
+ {
+ public ActionBindingContext(ActionContext context,
+ IModelMetadataProvider metadataProvider,
+ IModelBinder modelBinder,
+ IValueProvider valueProvider,
+ IInputFormatter inputFormatter)
+ {
+ ActionContext = context;
+ MetadataProvider = metadataProvider;
+ ModelBinder = modelBinder;
+ ValueProvider = valueProvider;
+ InputFormatter = inputFormatter;
+ }
+
+ public ActionContext ActionContext { get; private set; }
+
+ public IModelMetadataProvider MetadataProvider { get; private set; }
+
+ public IModelBinder ModelBinder { get; private set; }
+
+ public IValueProvider ValueProvider { get; private set; }
+
+ public IInputFormatter InputFormatter { get; private set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs
new file mode 100644
index 0000000000..9b515aec14
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Mvc.ModelBinding;
+
+namespace Microsoft.AspNet.Mvc
+{
+ public class DefaultActionBindingContextProvider : IActionBindingContextProvider
+ {
+ private readonly IModelMetadataProvider _modelMetadataProvider;
+ private readonly IEnumerable _modelBinders;
+ private readonly IEnumerable _valueProviderFactories;
+ private readonly IEnumerable _bodyReaders;
+
+ public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
+ IEnumerable modelBinders,
+ IEnumerable valueProviderFactories,
+ IEnumerable bodyReaders)
+ {
+ _modelMetadataProvider = modelMetadataProvider;
+ _modelBinders = modelBinders.OrderBy(binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0);
+ _valueProviderFactories = valueProviderFactories;
+ _bodyReaders = bodyReaders;
+ }
+
+ public async Task GetActionBindingContextAsync(ActionContext actionContext)
+ {
+ var requestContext = new RequestContext(actionContext.HttpContext, actionContext.RouteValues);
+ var valueProviders = await Task.WhenAll(_valueProviderFactories.Select(factory => factory.GetValueProviderAsync(requestContext)));
+ valueProviders = valueProviders.Where(vp => vp != null)
+ .ToArray();
+
+ return new ActionBindingContext(
+ actionContext,
+ _modelMetadataProvider,
+ new CompositeModelBinder(_modelBinders),
+ new CompositeValueProvider(valueProviders),
+ new CompositeInputFormatter(_bodyReaders)
+ );
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/FromBodyAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/FromBodyAttribute.cs
new file mode 100644
index 0000000000..4eae2f9f03
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/FromBodyAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Microsoft.AspNet.Mvc
+{
+ [AttributeUsage(AttributeTargets.Parameter)]
+ public sealed class FromBodyAttribute : Attribute
+ {
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/IActionBindingContextProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/IActionBindingContextProvider.cs
new file mode 100644
index 0000000000..838768c25e
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/IActionBindingContextProvider.cs
@@ -0,0 +1,10 @@
+using System.Threading.Tasks;
+using Microsoft.AspNet.Mvc.ModelBinding;
+
+namespace Microsoft.AspNet.Mvc
+{
+ public interface IActionBindingContextProvider
+ {
+ Task GetActionBindingContextAsync(ActionContext actionContext);
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBindingInfo.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBindingInfo.cs
index eae59a2dba..f4e5830984 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ParameterBindingInfo.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBindingInfo.cs
@@ -1,13 +1,17 @@
-
+using System;
+
namespace Microsoft.AspNet.Mvc
{
- // This is a placeholder and is missing things that we'll need for real model binding
public class ParameterBindingInfo
{
- public bool IsOptional { get; set; }
+ public ParameterBindingInfo(string prefix, Type parameterType)
+ {
+ Prefix = prefix;
+ ParameterType = parameterType;
+ }
- public bool IsFromBody { get; set; }
+ public string Prefix { get; private set; }
- public string Prefix { get; set; }
+ public Type ParameterType { get; private set; }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterDescriptor.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterDescriptor.cs
index f4d6a65778..ca295bcd99 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ParameterDescriptor.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterDescriptor.cs
@@ -1,4 +1,4 @@
-
+using System;
namespace Microsoft.AspNet.Mvc
{
@@ -6,6 +6,10 @@ namespace Microsoft.AspNet.Mvc
{
public string Name { get; set; }
- public ParameterBindingInfo Binding { get; set; }
+ public bool IsOptional { get; set; }
+
+ public ParameterBindingInfo ParameterBindingInfo { get; set; }
+
+ public BodyParameterInfo BodyParameterInfo { get; set; }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs
index 11a1f0621b..0a97918845 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs
@@ -1,8 +1,11 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Mvc.Internal;
+using Microsoft.AspNet.Mvc.ModelBinding;
namespace Microsoft.AspNet.Mvc
{
@@ -13,21 +16,24 @@ namespace Microsoft.AspNet.Mvc
private readonly IActionResultFactory _actionResultFactory;
private readonly IServiceProvider _serviceProvider;
private readonly IControllerFactory _controllerFactory;
+ private readonly IActionBindingContextProvider _bindingProvider;
public ReflectedActionInvoker(ActionContext actionContext,
ReflectedActionDescriptor descriptor,
IActionResultFactory actionResultFactory,
IControllerFactory controllerFactory,
+ IActionBindingContextProvider bindingContextProvider,
IServiceProvider serviceProvider)
{
_actionContext = actionContext;
_descriptor = descriptor;
_actionResultFactory = actionResultFactory;
_controllerFactory = controllerFactory;
+ _bindingProvider = bindingContextProvider;
_serviceProvider = serviceProvider;
}
- public Task InvokeActionAsync()
+ public async Task InvokeActionAsync()
{
IActionResult actionResult = null;
@@ -39,7 +45,8 @@ namespace Microsoft.AspNet.Mvc
}
else
{
- Initialize(controller);
+ var modelState = new ModelStateDictionary();
+ InitializeController(controller, modelState);
var method = _descriptor.MethodInfo;
@@ -49,17 +56,19 @@ namespace Microsoft.AspNet.Mvc
}
else
{
- object actionReturnValue = method.Invoke(controller, null);
+ var parameterValues = await GetParameterValues(modelState);
+
+ object actionReturnValue = method.Invoke(controller, GetArgumentValues(parameterValues));
actionResult = _actionResultFactory.CreateActionResult(method.ReturnType, actionReturnValue, _actionContext);
}
}
// TODO: This will probably move out once we got filters
- return actionResult.ExecuteResultAsync(_actionContext);
+ await actionResult.ExecuteResultAsync(_actionContext);
}
- private void Initialize(object controller)
+ private void InitializeController(object controller, ModelStateDictionary modelState)
{
var controllerType = controller.GetType();
@@ -72,6 +81,10 @@ namespace Microsoft.AspNet.Mvc
prop.SetValue(controller, _actionContext.HttpContext);
}
}
+ else if (prop.Name == "ModelState" && prop.PropertyType == typeof(ModelStateDictionary))
+ {
+ prop.SetValue(controller, modelState);
+ }
}
var method = controllerType.GetRuntimeMethods().FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
@@ -86,5 +99,57 @@ namespace Microsoft.AspNet.Mvc
method.Invoke(controller, args);
}
+
+ private async Task> GetParameterValues(ModelStateDictionary modelState)
+ {
+ var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(_actionContext);
+ var parameters = _descriptor.Parameters;
+
+ var parameterValues = new Dictionary(parameters.Count, StringComparer.Ordinal);
+ for (int i = 0; i < parameters.Count; i++)
+ {
+ var parameter = parameters[i];
+ if (parameter.BodyParameterInfo != null)
+ {
+ var inputFormatterContext = actionBindingContext.CreateInputFormatterContext(
+ modelState,
+ parameter);
+ await actionBindingContext.InputFormatter.ReadAsync(inputFormatterContext);
+ parameterValues[parameter.Name] = inputFormatterContext.Model;
+ }
+ else
+ {
+ var modelBindingContext = actionBindingContext.CreateModelBindingContext(
+ modelState,
+ parameter);
+ actionBindingContext.ModelBinder.BindModel(modelBindingContext);
+ parameterValues[parameter.Name] = modelBindingContext.Model;
+ }
+
+ }
+
+ return parameterValues;
+ }
+
+ private object[] GetArgumentValues(IDictionary parameterValues)
+ {
+ var parameters = _descriptor.MethodInfo.GetParameters();
+ var arguments = new object[parameters.Length];
+
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ object value;
+ if (parameterValues.TryGetValue(parameters[i].Name, out value))
+ {
+ arguments[i] = value;
+ }
+ else
+ {
+ arguments[i] = parameters[i].DefaultValue;
+ }
+ }
+
+ return arguments;
+ }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/CompositeInputFormatter.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/CompositeInputFormatter.cs
new file mode 100644
index 0000000000..6386bcfe04
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/CompositeInputFormatter.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public class CompositeInputFormatter : IInputFormatter
+ {
+ private IInputFormatter[] _bodyReaders;
+
+ public CompositeInputFormatter(IEnumerable bodyReaders)
+ {
+ _bodyReaders = bodyReaders.ToArray();
+ }
+
+ public async Task ReadAsync(InputFormatterContext context)
+ {
+ for(int i = 0; i < _bodyReaders.Length; i++)
+ {
+ if (await _bodyReaders[i].ReadAsync(context))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/IInputFormatter.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/IInputFormatter.cs
new file mode 100644
index 0000000000..d32c85a9c2
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/IInputFormatter.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public interface IInputFormatter
+ {
+ Task ReadAsync(InputFormatterContext context);
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/InputFormatterContext.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/InputFormatterContext.cs
new file mode 100644
index 0000000000..f123e66293
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/InputFormatterContext.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public class InputFormatterContext
+ {
+ public InputFormatterContext(ModelMetadata metadata, ModelStateDictionary modelState)
+ {
+ Metadata = metadata;
+ ModelState = modelState;
+ }
+
+ public ModelMetadata Metadata { get; private set; }
+
+ public ModelStateDictionary ModelState { get; private set; }
+
+ public object Model { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/JsonInputFormatter.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/JsonInputFormatter.cs
new file mode 100644
index 0000000000..269f3077a5
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/JsonInputFormatter.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public class JsonInputFormatter : IInputFormatter
+ {
+ public Task ReadAsync(InputFormatterContext bindingContext)
+ {
+ return Task.FromResult(false);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
index 1ee8243f00..1c3a593b88 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@@ -14,8 +15,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
}
- public CompositeValueProvider(IList list)
- : base(list)
+ public CompositeValueProvider(IEnumerable valueProviders)
+ : base(valueProviders.ToList())
{
}
diff --git a/src/Microsoft.AspNet.Mvc/MvcServices.cs b/src/Microsoft.AspNet.Mvc/MvcServices.cs
index 789ebf9bd1..d7767fb661 100644
--- a/src/Microsoft.AspNet.Mvc/MvcServices.cs
+++ b/src/Microsoft.AspNet.Mvc/MvcServices.cs
@@ -4,7 +4,6 @@ using Microsoft.AspNet.DependencyInjection.NestedProviders;
using Microsoft.AspNet.FileSystems;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
-using Microsoft.AspNet.Mvc.Razor.Compilation;
namespace Microsoft.AspNet.Mvc
{
@@ -28,8 +27,6 @@ namespace Microsoft.AspNet.Mvc
Add();
Add();
Add();
- Add();
- Add();
Add();
Add();
AddInstance(new PhysicalFileSystem(appRoot));
@@ -48,11 +45,25 @@ namespace Microsoft.AspNet.Mvc
Add();
Add();
+ Add();
+ Add();
+
// This is temporary until DI has some magic for it
Add, NestedProviderManager>();
Add, NestedProviderManager>();
Add, ReflectedActionDescriptorProvider>();
Add, ActionInvokerProvider>();
+
+ Add();
+ Add();
+
+ Add();
+ Add();
+ Add();
+ Add();
+ Add();
+
+ Add();
}
private void Add() where TU : T