// 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.Threading.Tasks;
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.
///
protected abstract Task BindModelCoreAsync([NotNull] ModelBindingContext bindingContext);
///
public async Task BindModelAsync(ModelBindingContext context)
{
var allowedBindingSource = context.ModelMetadata.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 null;
}
var result = await BindModelCoreAsync(context);
var modelBindingResult =
result != null ?
new ModelBindingResult(result.Model, result.Key, result.IsModelSet) :
new ModelBindingResult(null, context.ModelName, false);
// Prevent other model binders from running because this model binder is the only handler for
// its binding source.
return modelBindingResult;
}
}
}