// 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.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding { /// /// An which provides data from a specific . /// /// /// /// A is an base-implementation which /// can provide data for all parameters and model properties which specify the corresponding /// . /// /// /// is greedy, meaning that a given instance expects to handle all /// parameters and properties annotated with the corresponding and /// will short-circuit the model binding process to prevent other binders from running. /// of must be set to true. /// /// public abstract class BindingSourceModelBinder : IModelBinder { /// /// Creates a new . /// /// /// The . Must be a single-source (non-composite) with /// equal to true. /// protected BindingSourceModelBinder([NotNull] BindingSource bindingSource) { // This class implements a pattern that's only useful for greedy model binders. If you need // to implement something non-greedy then don't use the base class. if (!bindingSource.IsGreedy) { var message = Resources.FormatBindingSource_MustBeGreedy( bindingSource.DisplayName, nameof(BindingSourceModelBinder)); throw new ArgumentException(message, nameof(bindingSource)); } BindingSource = bindingSource; } /// /// Gets the corresponding . /// protected BindingSource BindingSource { get; } /// /// Binds the model. Called when the model's supported binding-source matches . /// /// The . /// /// A which will complete when model binding has completed. /// /// /// Other model binders will never run if this method is called. Return null to skip other model binders /// but allow higher-level handling e.g. falling back to empty prefix. /// protected abstract Task BindModelCoreAsync([NotNull] ModelBindingContext bindingContext); /// public async Task BindModelAsync(ModelBindingContext context) { var allowedBindingSource = context.BindingSource; if (allowedBindingSource == null || !allowedBindingSource.CanAcceptDataFrom(BindingSource)) { // Binding Sources are opt-in. This model either didn't specify one or specified something // incompatible so let other binders run. return ModelBindingResult.NoResult; } var result = await BindModelCoreAsync(context); var modelBindingResult = result != ModelBindingResult.NoResult ? result : 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. return modelBindingResult; } } }