// 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.Linq; using System.Reflection; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Core; namespace Microsoft.AspNetCore.Mvc { /// /// API conventions to be applied to a controller action. /// /// API conventions are used to influence the output of ApiExplorer. /// can be used to specify an exact convention method that applies /// to an action. for details about applying conventions at /// the assembly or controller level. /// /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public sealed class ApiConventionMethodAttribute : Attribute { /// /// Initializes an instance using and /// the specified . /// /// /// The of the convention. /// /// Conventions must be static types. Methods in a convention are /// matched to an action method using rules specified by /// that may be applied to a method name or it's parameters and /// that are applied to parameters. /// /// /// The method name. public ApiConventionMethodAttribute(Type conventionType, string methodName) { ConventionType = conventionType ?? throw new ArgumentNullException(nameof(conventionType)); ApiConventionTypeAttribute.EnsureValid(conventionType); if (string.IsNullOrEmpty(methodName)) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(methodName)); } Method = GetConventionMethod(conventionType, methodName); } private static MethodInfo GetConventionMethod(Type conventionType, string methodName) { var methods = conventionType.GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(method => method.Name == methodName) .ToArray(); if (methods.Length == 0) { throw new ArgumentException(Resources.FormatApiConventionMethod_NoMethodFound(methodName, conventionType), nameof(methodName)); } else if (methods.Length > 1) { throw new ArgumentException(Resources.FormatApiConventionMethod_AmbigiousMethodName(methodName, conventionType), nameof(methodName)); } return methods[0]; } /// /// Gets the convention type. /// public Type ConventionType { get; } internal MethodInfo Method { get; } } }