// Copyright (c) Microsoft Open Technologies, Inc. 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.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding { /// /// An which binds models from the request body using an /// when a model has the binding source / /// public class BodyModelBinder : BindingSourceModelBinder { private readonly ActionContext _actionContext; private readonly IScopedInstance _bindingContext; private readonly IInputFormatterSelector _formatterSelector; private readonly IValidationExcludeFiltersProvider _bodyValidationExcludeFiltersProvider; /// /// Creates a new . /// /// An accessor to the . /// An accessor to the . /// The . /// /// The . /// public BodyModelBinder([NotNull] IScopedInstance context, [NotNull] IScopedInstance bindingContext, [NotNull] IInputFormatterSelector selector, [NotNull] IValidationExcludeFiltersProvider bodyValidationExcludeFiltersProvider) : base(BindingSource.Body) { _actionContext = context.Value; _bindingContext = bindingContext; _formatterSelector = selector; _bodyValidationExcludeFiltersProvider = bodyValidationExcludeFiltersProvider; } /// protected async override Task BindModelCoreAsync([NotNull] ModelBindingContext bindingContext) { var formatters = _bindingContext.Value.InputFormatters; var formatterContext = new InputFormatterContext(_actionContext, bindingContext.ModelType); var formatter = _formatterSelector.SelectFormatter(formatters.ToList(), formatterContext); if (formatter == null) { var unsupportedContentType = Resources.FormatUnsupportedContentType( bindingContext.OperationBindingContext.HttpContext.Request.ContentType); bindingContext.ModelState.AddModelError(bindingContext.ModelName, unsupportedContentType); return new ModelBindingResult(null, bindingContext.ModelName, isModelSet: false); } object model = null; try { model = await formatter.ReadAsync(formatterContext); } catch (Exception ex) { model = GetDefaultValueForType(bindingContext.ModelType); bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex); return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } private object GetDefaultValueForType(Type modelType) { if (modelType.GetTypeInfo().IsValueType) { return Activator.CreateInstance(modelType); } return null; } } }