// 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.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Mvc.ApplicationModels { [DebuggerDisplay("{DisplayName}")] public class ActionModel : ICommonModel, IFilterModel, IApiExplorerModel { public ActionModel( MethodInfo actionMethod, IReadOnlyList attributes) { if (actionMethod == null) { throw new ArgumentNullException(nameof(actionMethod)); } if (attributes == null) { throw new ArgumentNullException(nameof(attributes)); } ActionMethod = actionMethod; ApiExplorer = new ApiExplorerModel(); Attributes = new List(attributes); Filters = new List(); Parameters = new List(); RouteValues = new Dictionary(StringComparer.OrdinalIgnoreCase); Properties = new Dictionary(); Selectors = new List(); } public ActionModel(ActionModel other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } ActionMethod = other.ActionMethod; ActionName = other.ActionName; // Not making a deep copy of the controller, this action still belongs to the same controller. Controller = other.Controller; // These are just metadata, safe to create new collections Attributes = new List(other.Attributes); Filters = new List(other.Filters); Properties = new Dictionary(other.Properties); RouteValues = new Dictionary(other.RouteValues, StringComparer.OrdinalIgnoreCase); // Make a deep copy of other 'model' types. ApiExplorer = new ApiExplorerModel(other.ApiExplorer); Parameters = new List(other.Parameters.Select(p => new ParameterModel(p) { Action = this })); Selectors = new List(other.Selectors.Select(s => new SelectorModel(s))); } public MethodInfo ActionMethod { get; } public string ActionName { get; set; } /// /// Gets or sets the for this action. /// /// /// allows configuration of settings for ApiExplorer /// which apply to the action. /// /// Settings applied by override settings from /// and . /// public ApiExplorerModel ApiExplorer { get; set; } public IReadOnlyList Attributes { get; } public ControllerModel Controller { get; set; } public IList Filters { get; } public IList Parameters { get; } /// /// Gets a collection of route values that must be present in the /// for the corresponding action to be selected. /// /// /// /// The value of is considered an implicit route value corresponding /// to the key action and the value of is /// considered an implicit route value corresponding to the key controller. These entries /// will be implicitly added to when the action /// descriptor is created, but will not be visible in . /// /// /// Entries in can override entries in /// . /// /// public IDictionary RouteValues { get; } /// /// Gets a set of properties associated with the action. /// These properties will be copied to . /// /// /// Entries will take precedence over entries with the same key in /// and . /// public IDictionary Properties { get; } MemberInfo ICommonModel.MemberInfo => ActionMethod; string ICommonModel.Name => ActionName; public IList Selectors { get; } public string DisplayName { get { if (Controller == null) { return ActionMethod.Name; } var controllerType = TypeNameHelper.GetTypeDisplayName(Controller.ControllerType); var controllerAssembly = Controller?.ControllerType.Assembly.GetName().Name; return $"{controllerType}.{ActionMethod.Name} ({controllerAssembly})"; } } } }