public void OnProvidersExecuting(ApiDescriptionProviderContext context)
        {
            foreach (var apiDescription in context.Results)
            {
                if (!apiDescription.ActionDescriptor.FilterDescriptors.Any(f => f.Filter is IApiBehaviorMetadata))
                {
                    continue;
                }

                var parameters = apiDescription.ActionDescriptor.Parameters.Concat(apiDescription.ActionDescriptor.BoundProperties);
                if (parameters.Any())
                {
                    apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(StatusCodes.Status400BadRequest));

                    if (parameters.Any(p => p.Name.EndsWith("id", StringComparison.OrdinalIgnoreCase)))
                    {
                        apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(StatusCodes.Status404NotFound));
                    }
                }

                // We don't have a good way to signal a "default" response type. We'll use 0 to indicate this until we come up
                // with something better.
                apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(statusCode: 0));
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            var ignoreApiExplorerSettings = !Options.UseApiExplorerSettings;
            var mappings        = RouteCollectionProvider.Items;
            var results         = context.Results;
            var groupNameFormat = Options.GroupNameFormat;
            var formatProvider  = CultureInfo.CurrentCulture;

            foreach (var action in context.Actions.OfType <ControllerActionDescriptor>())
            {
                if (!action.ControllerTypeInfo.IsODataController() || action.ControllerTypeInfo.IsMetadataController())
                {
                    continue;
                }

                var controller  = action.GetProperty <ControllerModel>();
                var apiExplorer = controller?.ApiExplorer;
                var visible     = ignoreApiExplorerSettings || (apiExplorer?.IsVisible ?? true);

                if (!visible)
                {
                    continue;
                }

                var model = GetModel(action);

                if (model.IsApiVersionNeutral)
                {
                    foreach (var mapping in mappings)
                    {
                        var groupName = mapping.ApiVersion.ToString(groupNameFormat, formatProvider);

                        foreach (var apiDescription in NewODataApiDescriptions(action, groupName, mapping))
                        {
                            results.Add(apiDescription);
                        }
                    }
                }
                else
                {
                    foreach (var apiVersion in model.DeclaredApiVersions)
                    {
                        var groupName = apiVersion.ToString(groupNameFormat, formatProvider);

                        if (!mappings.TryGetValue(apiVersion, out var mappingsPerApiVersion))
                        {
                            continue;
                        }

                        foreach (var mapping in mappingsPerApiVersion)
                        {
                            foreach (var apiDescription in NewODataApiDescriptions(action, groupName, mapping))
                            {
                                results.Add(apiDescription);
                            }
                        }
                    }
                }
            }
        }
        /// <inheritdoc />
        public void OnProvidersExecuting(ApiDescriptionProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            foreach (var action in context.Actions.OfType <ControllerActionDescriptor>())
            {
                if (action.AttributeRouteInfo != null && action.AttributeRouteInfo.SuppressPathMatching)
                {
                    continue;
                }

                var extensionData = action.GetProperty <ApiDescriptionActionData>();
                if (extensionData != null)
                {
                    var httpMethods = GetHttpMethods(action);
                    foreach (var httpMethod in httpMethods)
                    {
                        context.Results.Add(CreateApiDescription(action, httpMethod, extensionData.GroupName));
                    }
                }
            }
        }
        /// <inheritdoc />
        public void OnProvidersExecuting(ApiDescriptionProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            foreach (var action in context.Actions.OfType <ControllerActionDescriptor>())
            {
                if (action.AttributeRouteInfo != null && action.AttributeRouteInfo.SuppressPathMatching)
                {
                    continue;
                }

                // ApiDescriptionActionData is only added to the ControllerActionDescriptor if
                // the action is marked as `IsVisible` to the ApiExplorer. This null-check is
                // effectively asserting if the endpoint should be generated into the final
                // OpenAPI metadata.
                var extensionData = action.GetProperty <ApiDescriptionActionData>();
                if (extensionData != null)
                {
                    var httpMethods = GetHttpMethods(action);
                    foreach (var httpMethod in httpMethods)
                    {
                        context.Results.Add(CreateApiDescription(action, httpMethod, GetGroupName(action, extensionData)));
                    }
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var results         = context.Results;
            var mappings        = RouteCollectionProvider.Items;
            var groupNameFormat = Options.GroupNameFormat;
            var formatProvider  = CultureInfo.CurrentCulture;

            foreach (var action in context.Actions.OfType <ControllerActionDescriptor>())
            {
                if (!action.ControllerTypeInfo.IsODataController() ||
                    action.ControllerTypeInfo.IsMetadataController() ||
                    !IsVisible(action))
                {
                    continue;
                }

                for (var i = 0; i < mappings.Count; i++)
                {
                    var mapping = mappings[i];

                    if (!IsMappedTo(action, mapping))
                    {
                        continue;
                    }

                    var mappedVersions = mapping.ModelSelector.ApiVersions;

                    for (var j = 0; j < mappedVersions.Count; j++)
                    {
                        var apiVersion = mappedVersions[j];

                        if (!action.IsMappedTo(apiVersion))
                        {
                            continue;
                        }

                        var groupName    = apiVersion.ToString(groupNameFormat, formatProvider);
                        var descriptions = new List <ApiDescription>();

                        foreach (var apiDescription in NewODataApiDescriptions(action, apiVersion, groupName, mapping))
                        {
                            results.Add(apiDescription);
                            descriptions.Add(apiDescription);
                        }

                        if (descriptions.Count > 0)
                        {
                            ExploreQueryOptions(descriptions, mapping.Services.GetRequiredService <ODataUriResolver>());
                        }
                    }
                }
            }
        }
        internal static IReadOnlyList <ApiDescription> Execute(this IApiDescriptionProvider apiDescriptionProvider, ActionDescriptor actionDescriptor)
        {
            var context = new ApiDescriptionProviderContext(new[] { actionDescriptor });

            apiDescriptionProvider.OnProvidersExecuting(context);
            apiDescriptionProvider.OnProvidersExecuted(context);

            return(context.Results.ToArray());
        }
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var results = context.Results;

            if (results.Count == 0)
            {
                return;
            }

            var groupResults = new List <ApiDescription>();

            foreach (var version in FlattenApiVersions(results))
            {
                var groupName = version.ToString(Options.GroupNameFormat, CurrentCulture);

                foreach (var result in results)
                {
                    var action = result.ActionDescriptor;

                    if (!ShouldExploreAction(action, version))
                    {
                        continue;
                    }

                    var groupResult = result.Clone();

                    if (string.IsNullOrEmpty(groupResult.GroupName))
                    {
                        groupResult.GroupName = groupName;
                    }

                    groupResult.SetApiVersion(version);
                    PopulateApiVersionParameters(groupResult, version);
                    groupResult.TryUpdateRelativePathAndRemoveApiVersionParameter(Options);
                    groupResults.Add(groupResult);
                }
            }

            results.Clear();

            foreach (var result in groupResults)
            {
                results.Add(result);
            }
        }
Esempio n. 8
0
        public void OnProvidersExecuting(ApiDescriptionProviderContext context)
        {
            foreach (var description in context.Results)
            {
                if (!AppliesTo(description))
                {
                    continue;
                }

                foreach (var responseType in CreateProblemResponseTypes(description))
                {
                    description.SupportedResponseTypes.Add(responseType);
                }
            }
        }
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            var results = context.Results;

            if (results.Count == 0)
            {
                return;
            }

            var groupResults    = new List <ApiDescription>();
            var parameterSource = Options.ApiVersionParameterSource;

            foreach (var version in FlattenApiVersions(results))
            {
                var groupName = version.ToString(Options.GroupNameFormat, CurrentCulture);

                foreach (var result in results)
                {
                    var action = result.ActionDescriptor;

                    if (!ShouldExploreAction(action, version))
                    {
                        continue;
                    }

                    var groupResult = result.Clone();

                    groupResult.GroupName = groupName;
                    groupResult.SetApiVersion(version);
                    PopulateApiVersionParameters(groupResult, version);

                    if (Options.SubstituteApiVersionInUrl)
                    {
                        UpdateRelativePathAndRemoveApiVersionParameterIfNecessary(groupResult, Options.SubstitutionFormat);
                    }

                    groupResults.Add(groupResult);
                }
            }

            results.Clear();

            foreach (var result in groupResults)
            {
                results.Add(result);
            }
        }
Esempio n. 10
0
 public void OnProvidersExecuting(ApiDescriptionProviderContext context)
 {
     foreach (var endpoint in _endpointDataSource.Endpoints)
     {
         if (endpoint is RouteEndpoint routeEndpoint &&
             routeEndpoint.Metadata.GetMetadata <MethodInfo>() is { } methodInfo&&
             routeEndpoint.Metadata.GetMetadata <IHttpMethodMetadata>() is { } httpMethodMetadata)
         {
             // REVIEW: Should we add an ApiDescription for endpoints without IHttpMethodMetadata? Swagger doesn't handle
             // a null HttpMethod even though it's nullable on ApiDescription, so we'd need to define "default" HTTP methods.
             // In practice, the Delegate will be called for any HTTP method if there is no IHttpMethodMetadata.
             foreach (var httpMethod in httpMethodMetadata.HttpMethods)
             {
                 context.Results.Add(CreateApiDescription(routeEndpoint, httpMethod, methodInfo));
             }
         }
     }
 }
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            var results = context.Results;

            if (results.Count == 0)
            {
                return;
            }

            var groupResults        = new List <ApiDescription>();
            var stringModelMetadata = new Lazy <ModelMetadata>(() => MetadadataProvider.GetMetadataForType(typeof(string)));

            foreach (var version in FlattenApiVersions(results))
            {
                var groupName = version.ToString(Options.GroupNameFormat, CurrentCulture);

                foreach (var result in results)
                {
                    var action = result.ActionDescriptor;

                    if (ShouldExploreAction(action, version))
                    {
                        foreach (var parameter in result.ParameterDescriptions)
                        {
                            ApplyModelMetadataIfNecessary(parameter, stringModelMetadata);
                        }

                        var groupResult = result.Clone();

                        groupResult.GroupName = groupName;
                        groupResult.SetApiVersion(version);
                        groupResults.Add(groupResult);
                    }
                }
            }

            results.Clear();

            foreach (var result in groupResults)
            {
                results.Add(result);
            }
        }
        private ApiDescriptionGroupCollection GetCollection(ActionDescriptorCollection actionDescriptors)
        {
            var context = new ApiDescriptionProviderContext(actionDescriptors.Items);

            foreach (var provider in _apiDescriptionProviders)
            {
                provider.OnProvidersExecuting(context);
            }

            for (var i = _apiDescriptionProviders.Length - 1; i >= 0; i--)
            {
                _apiDescriptionProviders[i].OnProvidersExecuted(context);
            }

            var groups = context.Results
                         .GroupBy(d => d.GroupName)
                         .Select(g => new ApiDescriptionGroup(g.Key, g.ToArray()))
                         .ToArray();

            return(new ApiDescriptionGroupCollection(groups, actionDescriptors.Version));
        }
Esempio n. 13
0
        private ApiDescriptionGroupCollection GetCollection(ActionDescriptorCollection actionDescriptors)
        {
            var filtered = actionDescriptors.Items
                           .Where(ad => ad.RouteValues.TryGetValue("area", out var area) && area == "Api")
                           .ToList();
            var context = new ApiDescriptionProviderContext(filtered);

            foreach (var provider in _apiDescriptionProviders)
            {
                provider.OnProvidersExecuting(context);
            }

            for (var i = _apiDescriptionProviders.Length - 1; i >= 0; i--)
            {
                _apiDescriptionProviders[i].OnProvidersExecuted(context);
            }

            var groups = context.Results
                         .GroupBy(d => d.GroupName)
                         .Select(g => new ApiDescriptionGroup(g.Key, g.ToArray()))
                         .ToArray();

            return(new ApiDescriptionGroupCollection(groups, actionDescriptors.Version));
        }
Esempio n. 14
0
        public void versioned_api_explorer_should_group_and_order_descriptions_on_providers_executed()
        {
            // arrange
            var actionProvider        = new TestActionDescriptorCollectionProvider();
            var context               = new ApiDescriptionProviderContext(actionProvider.ActionDescriptors.Items);
            var groupNameFormatter    = new DefaultApiVersionGroupNameFormatter();
            var modelMetadataProvider = NewModelMetadataProvider();
            var apiExplorer           = new VersionedApiDescriptionProvider(groupNameFormatter, modelMetadataProvider);

            foreach (var action in context.Actions)
            {
                context.Results.Add(new ApiDescription()
                {
                    ActionDescriptor = action
                });
            }

            // act
            apiExplorer.OnProvidersExecuted(context);

            // assert
            context.Results.ShouldBeEquivalentTo(
                new[]
            {
                // orders
                new { GroupName = "v0.9", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(0, 9)
                      } },
                new { GroupName = "v1", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(1, 0)
                      } },
                new { GroupName = "v1", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(1, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },

                // people
                new { GroupName = "v0.9", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(0, 9)
                      } },
                new { GroupName = "v1", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(1, 0)
                      } },
                new { GroupName = "v1", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(1, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v2", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(2, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
                new { GroupName = "v3", Properties = new Dictionary <object, object>()
                      {
                          [typeof(ApiVersion)] = new ApiVersion(3, 0)
                      } },
            },
                options => options.ExcludingMissingMembers());
        }
 public void OnProvidersExecuted(ApiDescriptionProviderContext context)
 {
 }
 /// <summary>
 /// Occurs when the providers are being executed.
 /// </summary>
 /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
 /// <remarks>The default implementation performs no operation.</remarks>
 public virtual void OnProvidersExecuting(ApiDescriptionProviderContext context)
 {
 }
        /// <summary>
        /// Occurs after the providers have been executed.
        /// </summary>
        /// <param name="context">The current <see cref="ApiDescriptionProviderContext">execution context</see>.</param>
        /// <remarks>The default implementation performs no action.</remarks>
        public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context)
        {
            var ignoreApiExplorerSettings = !Options.UseApiExplorerSettings;
            var mappings = RouteCollectionProvider.Items;
            var results  = context.Results;

            var groupNameFormat = Options.GroupNameFormat;
            var formatProvider  = CultureInfo.CurrentCulture;

            foreach (var action in context.Actions.OfType <ControllerActionDescriptor>())
            {
                if (!action.ControllerTypeInfo.IsODataController() ||
                    action.ControllerTypeInfo.IsMetadataController() ||
                    !IsVisible(action))
                {
                    continue;
                }

                var model = action.GetApiVersionModel(Explicit | Implicit);

                if (model.IsApiVersionNeutral)
                {
                    foreach (var mapping in mappings)
                    {
                        var descriptions = new List <ApiDescription>();
                        var groupName    = mapping.ApiVersion.ToString(groupNameFormat, formatProvider);

                        foreach (var apiDescription in NewODataApiDescriptions(action, groupName, mapping))
                        {
                            results.Add(apiDescription);
                            descriptions.Add(apiDescription);
                        }

                        if (descriptions.Count > 0)
                        {
                            ExploreQueryOptions(descriptions, mapping.Services.GetRequiredService <ODataUriResolver>());
                        }
                    }
                }
                else
                {
                    foreach (var apiVersion in model.DeclaredApiVersions)
                    {
                        var groupName = apiVersion.ToString(groupNameFormat, formatProvider);

                        if (!mappings.TryGetValue(apiVersion, out var mappingsPerApiVersion))
                        {
                            continue;
                        }

                        foreach (var mapping in mappingsPerApiVersion)
                        {
                            var descriptions = new List <ApiDescription>();

                            foreach (var apiDescription in NewODataApiDescriptions(action, groupName, mapping))
                            {
                                results.Add(apiDescription);
                                descriptions.Add(apiDescription);
                            }

                            if (descriptions.Count > 0)
                            {
                                ExploreQueryOptions(descriptions, mapping.Services.GetRequiredService <ODataUriResolver>());
                            }
                        }
                    }
                }
            }
        }