| File: BindPropertyAttribute.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.ModelBinding; namespace Microsoft.AspNetCore.Mvc; /// <summary> /// An attribute that can specify a model name or type of <see cref="IModelBinder"/> to use for binding the /// associated property. /// </summary> /// <remarks> /// Similar to <see cref="ModelBinderAttribute"/>. Unlike that attribute, <see cref="BindPropertyAttribute"/> /// applies only to properties and adds an <see cref="IRequestPredicateProvider"/> implementation that by default /// indicates the property should not be bound for HTTP GET requests (see also <see cref="SupportsGet"/>). /// </remarks> [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class BindPropertyAttribute : Attribute, IModelNameProvider, IBinderTypeProviderMetadata, IRequestPredicateProvider { private static readonly Func<ActionContext, bool> _supportsAllRequests = (c) => true; private static readonly Func<ActionContext, bool> _supportsNonGetRequests = IsNonGetRequest; private BindingSource? _bindingSource; private Type? _binderType; /// <summary> /// Gets or sets an indication the associated property should be bound in HTTP GET requests. If /// <see langword="true"/>, the property should be bound in all requests. Otherwise, the property should not be /// bound in HTTP GET requests. /// </summary> /// <value>Defaults to <see langword="false"/>.</value> public bool SupportsGet { get; set; } /// <inheritdoc /> /// <remarks> /// Subclass this attribute and set <see cref="BindingSource"/> if <see cref="BindingSource.Custom"/> is not /// correct for the specified (non-<see langword="null"/>) <see cref="IModelBinder"/> implementation. /// </remarks> public Type? BinderType { get => _binderType; set { if (value != null && !typeof(IModelBinder).IsAssignableFrom(value)) { throw new ArgumentException( Resources.FormatBinderType_MustBeIModelBinder( value.FullName, typeof(IModelBinder).FullName), nameof(value)); } _binderType = value; } } /// <inheritdoc /> /// <value> /// If <see cref="BinderType"/> is <see langword="null"/>, defaults to <see langword="null"/>. Otherwise, /// defaults to <see cref="BindingSource.Custom"/>. May be overridden in a subclass. /// </value> public virtual BindingSource? BindingSource { get { if (_bindingSource == null && BinderType != null) { return BindingSource.Custom; } return _bindingSource; } protected set => _bindingSource = value; } /// <inheritdoc /> public string? Name { get; set; } Func<ActionContext, bool> IRequestPredicateProvider.RequestPredicate => SupportsGet ? _supportsAllRequests : _supportsNonGetRequests; private static bool IsNonGetRequest(ActionContext context) { return !HttpMethods.IsGet(context.HttpContext.Request.Method); } }