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)); } }
/// <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))); } } } }
/// <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); } }
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); } }
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)); }
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)); }
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>()); } } } } } }