| File: ApplicationModels\ActionModel.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 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; /// <summary> /// An application model for controller actions. /// </summary> [DebuggerDisplay("{DisplayName}")] public class ActionModel : ICommonModel, IFilterModel, IApiExplorerModel { /// <summary> /// Initializes a new instance of <see cref="ActionModel"/>. /// </summary> /// <param name="actionMethod">The action <see cref="MethodInfo"/>.</param> /// <param name="attributes">The attributes associated with the action.</param> public ActionModel( MethodInfo actionMethod, IReadOnlyList<object> attributes) { ArgumentNullException.ThrowIfNull(actionMethod); ArgumentNullException.ThrowIfNull(attributes); ActionMethod = actionMethod; ApiExplorer = new ApiExplorerModel(); Attributes = new List<object>(attributes); Filters = new List<IFilterMetadata>(); Parameters = new List<ParameterModel>(); RouteValues = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase); Properties = new Dictionary<object, object?>(); Selectors = new List<SelectorModel>(); } /// <summary> /// Copy constructor for <see cref="ActionModel"/>. /// </summary> /// <param name="other">The <see cref="ActionModel"/> to copy.</param> public ActionModel(ActionModel other) { ArgumentNullException.ThrowIfNull(other); ActionMethod = other.ActionMethod; ActionName = other.ActionName; RouteParameterTransformer = other.RouteParameterTransformer; // 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<object>(other.Attributes); Filters = new List<IFilterMetadata>(other.Filters); Properties = new Dictionary<object, object?>(other.Properties); RouteValues = new Dictionary<string, string?>(other.RouteValues, StringComparer.OrdinalIgnoreCase); // Make a deep copy of other 'model' types. ApiExplorer = new ApiExplorerModel(other.ApiExplorer); Parameters = new List<ParameterModel>(other.Parameters.Select(p => new ParameterModel(p) { Action = this })); Selectors = new List<SelectorModel>(other.Selectors.Select(s => new SelectorModel(s))); } /// <summary> /// Gets the action <see cref="MethodInfo"/>. /// </summary> public MethodInfo ActionMethod { get; } /// <summary> /// Gets the action name. /// </summary> public string ActionName { get; set; } = default!; /// <summary> /// Gets or sets the <see cref="ApiExplorerModel"/> for this action. /// </summary> /// <remarks> /// <see cref="ActionModel.ApiExplorer"/> allows configuration of settings for ApiExplorer /// which apply to the action. /// /// Settings applied by <see cref="ActionModel.ApiExplorer"/> override settings from /// <see cref="ApplicationModel.ApiExplorer"/> and <see cref="ControllerModel.ApiExplorer"/>. /// </remarks> public ApiExplorerModel ApiExplorer { get; set; } /// <summary> /// Gets the attributes associated with the action. /// </summary> public IReadOnlyList<object> Attributes { get; } /// <summary> /// Gets or sets the <see cref="ControllerModel"/>. /// </summary> public ControllerModel Controller { get; set; } = default!; /// <summary> /// Gets the <see cref="IFilterMetadata"/> instances associated with the action. /// </summary> public IList<IFilterMetadata> Filters { get; } /// <summary> /// Gets the parameters associated with this action. /// </summary> public IList<ParameterModel> Parameters { get; } /// <summary> /// Gets or sets an <see cref="IOutboundParameterTransformer"/> that will be used to transform /// built-in route parameters such as <c>action</c>, <c>controller</c>, and <c>area</c> as well as /// additional parameters specified by <see cref="RouteValues"/> into static segments in the route template. /// </summary> /// <remarks> /// <para> /// This feature only applies when using endpoint routing. /// </para> /// </remarks> public IOutboundParameterTransformer? RouteParameterTransformer { get; set; } /// <summary> /// Gets a collection of route values that must be present in the /// <see cref="RouteData.Values"/> for the corresponding action to be selected. /// </summary> /// <remarks> /// <para> /// The value of <see cref="ActionName"/> is considered an implicit route value corresponding /// to the key <c>action</c> and the value of <see cref="ControllerModel.ControllerName"/> is /// considered an implicit route value corresponding to the key <c>controller</c>. These entries /// will be implicitly added to <see cref="ActionDescriptor.RouteValues"/> when the action /// descriptor is created, but will not be visible in <see cref="RouteValues"/>. /// </para> /// <para> /// Entries in <see cref="RouteValues"/> can override entries in /// <see cref="ControllerModel.RouteValues"/>. /// </para> /// </remarks> public IDictionary<string, string?> RouteValues { get; } /// <summary> /// Gets a set of properties associated with the action. /// These properties will be copied to <see cref="Abstractions.ActionDescriptor.Properties"/>. /// </summary> /// <remarks> /// Entries will take precedence over entries with the same key in /// <see cref="ApplicationModel.Properties"/> and <see cref="ControllerModel.Properties"/>. /// </remarks> public IDictionary<object, object?> Properties { get; } MemberInfo ICommonModel.MemberInfo => ActionMethod; string ICommonModel.Name => ActionName; /// <summary> /// Gets the <see cref="SelectorModel"/> instances. /// </summary> public IList<SelectorModel> Selectors { get; } /// <summary> /// Gets the action display name. /// </summary> 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})"; } } }