Consume ModelBinding from Mvc
* Modify ReflectedActionInvoker to model bind parameters * Introduce IBodyReader for reading request bodies * Introduce types for per-action-context specific binders, value providers and body readers
This commit is contained in:
parent
9dc79df9cf
commit
e87f8c372c
|
|
@ -10,6 +10,22 @@ namespace MvcSample
|
|||
return View("MyView", User());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action that exercises query\form based model binding.
|
||||
/// </summary>
|
||||
public IActionResult SaveUser(User user)
|
||||
{
|
||||
return View("MyView", user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action that exercises input formatter
|
||||
/// </summary>
|
||||
public IActionResult Post([FromBody]User user)
|
||||
{
|
||||
return View("MyView", user);
|
||||
}
|
||||
|
||||
public IActionResult Something()
|
||||
{
|
||||
return new ContentResult
|
||||
|
|
|
|||
|
|
@ -40,14 +40,16 @@ namespace MvcSample
|
|||
|
||||
var endpoint = ActivatorUtilities.CreateInstance<RouteEndpoint>(mvcServices.Services);
|
||||
|
||||
router.Add(new TemplateRoute(
|
||||
endpoint,
|
||||
"{controller}/{action}",
|
||||
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" }, { "action", "Index" } }));
|
||||
router.Add(new TemplateRoute(
|
||||
endpoint,
|
||||
"{controller}",
|
||||
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" } }));
|
||||
|
||||
router.Add(new TemplateRoute(
|
||||
endpoint,
|
||||
"{controller}/{action}",
|
||||
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) { { "controller", "Home" }, { "action", "Index" } }));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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<ActionDescriptorProviderContext> _actionDescriptorProvider;
|
||||
private readonly IEnumerable<IValueProviderFactory> _valueProviderFactory;
|
||||
private readonly IActionBindingContextProvider _bindingProvider;
|
||||
|
||||
public DefaultActionSelector(
|
||||
INestedProviderManager<ActionDescriptorProviderContext> actionDescriptorProvider,
|
||||
IEnumerable<IValueProviderFactory> valueProviderFactories)
|
||||
public DefaultActionSelector(INestedProviderManager<ActionDescriptorProviderContext> actionDescriptorProvider,
|
||||
IActionBindingContextProvider bindingProvider)
|
||||
{
|
||||
_actionDescriptorProvider = actionDescriptorProvider;
|
||||
_valueProviderFactory = valueProviderFactories;
|
||||
_bindingProvider = bindingProvider;
|
||||
}
|
||||
|
||||
public async Task<ActionDescriptor> SelectAsync(RequestContext context)
|
||||
|
|
@ -61,9 +59,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
protected virtual async Task<ActionDescriptor> SelectBestCandidate(RequestContext context, List<ActionDescriptor> candidates)
|
||||
{
|
||||
var valueProviders = await Task.WhenAll(_valueProviderFactory.Select(vpf => vpf.GetValueProviderAsync(context)));
|
||||
valueProviders = valueProviders.Where(vp => vp != null).ToArray();
|
||||
|
||||
var applicableCandiates = new List<ActionDescriptorCandidate>();
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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<FromBodyAttribute>() != null;
|
||||
}
|
||||
|
||||
private ParameterBindingInfo GetParameterBindingInfo(ParameterInfo parameter)
|
||||
{
|
||||
return new ParameterBindingInfo(parameter.Name, parameter.ParameterType);
|
||||
}
|
||||
|
||||
private BodyParameterInfo GetBodyParameterInfo(ParameterInfo parameter)
|
||||
{
|
||||
return new BodyParameterInfo(parameter.ParameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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<IModelBinder> _modelBinders;
|
||||
private readonly IEnumerable<IValueProviderFactory> _valueProviderFactories;
|
||||
private readonly IEnumerable<IInputFormatter> _bodyReaders;
|
||||
|
||||
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
||||
IEnumerable<IModelBinder> modelBinders,
|
||||
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
||||
IEnumerable<IInputFormatter> bodyReaders)
|
||||
{
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_modelBinders = modelBinders.OrderBy(binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0);
|
||||
_valueProviderFactories = valueProviderFactories;
|
||||
_bodyReaders = bodyReaders;
|
||||
}
|
||||
|
||||
public async Task<ActionBindingContext> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class FromBodyAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IActionBindingContextProvider
|
||||
{
|
||||
Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IDictionary<string, object>> GetParameterValues(ModelStateDictionary modelState)
|
||||
{
|
||||
var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(_actionContext);
|
||||
var parameters = _descriptor.Parameters;
|
||||
|
||||
var parameterValues = new Dictionary<string, object>(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<string, object> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IInputFormatter> bodyReaders)
|
||||
{
|
||||
_bodyReaders = bodyReaders.ToArray();
|
||||
}
|
||||
|
||||
public async Task<bool> ReadAsync(InputFormatterContext context)
|
||||
{
|
||||
for(int i = 0; i < _bodyReaders.Length; i++)
|
||||
{
|
||||
if (await _bodyReaders[i].ReadAsync(context))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public interface IInputFormatter
|
||||
{
|
||||
Task<bool> ReadAsync(InputFormatterContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class JsonInputFormatter : IInputFormatter
|
||||
{
|
||||
public Task<bool> ReadAsync(InputFormatterContext bindingContext)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<IValueProvider> list)
|
||||
: base(list)
|
||||
public CompositeValueProvider(IEnumerable<IValueProvider> valueProviders)
|
||||
: base(valueProviders.ToList())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IActionResultHelper, ActionResultHelper>();
|
||||
Add<IActionResultFactory, ActionResultFactory>();
|
||||
Add<IParameterDescriptorFactory, DefaultParameterDescriptorFactory>();
|
||||
Add<IValueProviderFactory, RouteValueValueProviderFactory>();
|
||||
Add<IValueProviderFactory, QueryStringValueProviderFactory>();
|
||||
Add<IControllerAssemblyProvider, AppDomainControllerAssemblyProvider>();
|
||||
Add<IActionDiscoveryConventions, DefaultActionDiscoveryConventions>();
|
||||
AddInstance<IFileSystem>(new PhysicalFileSystem(appRoot));
|
||||
|
|
@ -48,11 +45,25 @@ namespace Microsoft.AspNet.Mvc
|
|||
Add<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||
Add<IViewEngine, RazorViewEngine>();
|
||||
|
||||
Add<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
||||
Add<IActionBindingContextProvider, DefaultActionBindingContextProvider>();
|
||||
|
||||
// This is temporary until DI has some magic for it
|
||||
Add<INestedProviderManager<ActionDescriptorProviderContext>, NestedProviderManager<ActionDescriptorProviderContext>>();
|
||||
Add<INestedProviderManager<ActionInvokerProviderContext>, NestedProviderManager<ActionInvokerProviderContext>>();
|
||||
Add<INestedProvider<ActionDescriptorProviderContext>, ReflectedActionDescriptorProvider>();
|
||||
Add<INestedProvider<ActionInvokerProviderContext>, ActionInvokerProvider>();
|
||||
|
||||
Add<IValueProviderFactory, RouteValueValueProviderFactory>();
|
||||
Add<IValueProviderFactory, QueryStringValueProviderFactory>();
|
||||
|
||||
Add<IModelBinder, TypeConverterModelBinder>();
|
||||
Add<IModelBinder, TypeMatchModelBinder>();
|
||||
Add<IModelBinder, GenericModelBinder>();
|
||||
Add<IModelBinder, MutableObjectModelBinder>();
|
||||
Add<IModelBinder, ComplexModelDtoModelBinder>();
|
||||
|
||||
Add<IInputFormatter, JsonInputFormatter>();
|
||||
}
|
||||
|
||||
private void Add<T, TU>() where TU : T
|
||||
|
|
|
|||
Loading…
Reference in New Issue