public void OnProvidersExecuting(ApiDescriptionProviderContext context)
        {
            // will reuse some properties created by default provider
            var existingDescriptions = context.Results
                                       .Where(x => x.ActionDescriptor.GetProperty <MethodMetadata>() != null)
                                       .ToDictionary(x => x.ActionDescriptor);

            // clean up after default provider
            foreach (var apiDescription in existingDescriptions)
            {
                context.Results.Remove(apiDescription.Value);
            }

            var jsonRpcActions = context.Actions.Where(x => x.GetProperty <MethodMetadata>() != null);

            foreach (var action in jsonRpcActions)
            {
                if (!existingDescriptions.TryGetValue(action, out var originalDescription))
                {
                    // action was excluded from Results, eg because ignored with [ApiExplorerSettings(IgnoreApi = true)]
                    continue;
                }
                var actionXmlDoc          = (originalDescription.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetXmlDocsElement();
                var methodMetadata        = action.GetProperty <MethodMetadata>();
                var actionName            = methodMatcher.GetActionName(methodMetadata);
                var defaultSerializerType = options.DefaultMethodOptions.RequestSerializer;

                var apiDescription = new ApiDescription()
                {
                    ActionDescriptor        = action,
                    HttpMethod              = HttpMethods.Post,
                    RelativePath            = GetUniquePath(originalDescription.RelativePath, actionName),
                    SupportedRequestFormats =
                    {
                        JsonRequestFormat
                    },
                    SupportedResponseTypes =
                    {
                        // Single because more than 1 response type is a complicated scenario, don't know how to deal with it
                        WrapResponseType(actionName, originalDescription.SupportedResponseTypes.SingleOrDefault()?.Type, methodMetadata)
                    },
                    GroupName  = Utils.GetSwaggerFriendlyDocumentName(methodMetadata.MethodOptions.RequestSerializer, defaultSerializerType),
                    Properties =
                    {
                        [ApiExplorerConstants.ActionNameProperty] = actionName,
                    }
                };

                foreach (var parameterDescription in GetParameterDescriptions(actionName, originalDescription, methodMetadata, actionXmlDoc))
                {
                    apiDescription.ParameterDescriptions.Add(parameterDescription);
                }

                context.Results.Add(apiDescription);
            }
        }
Пример #2
0
        /// <summary>
        /// Prevent ambiguous and restricted routes
        /// </summary>
        internal void ValidateRouting(MethodMetadata methodMetadata)
        {
            var actionName = methodMatcher.GetActionName(methodMetadata);
            var key        = $"{methodMetadata.MethodOptions.Route}?{actionName}";

            if (KnownRoutes.TryGetValue(key, out var metadata))
            {
                throw new InvalidOperationException($"Route [{methodMetadata.MethodOptions.Route}], method [{methodMetadata}] conflicts with already mapped [{metadata}]");
            }

            if (actionName.StartsWith(JsonRpcConstants.ReservedMethodPrefix, StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException($"Route [{methodMetadata.MethodOptions.Route}], method [{methodMetadata}] starts with reserved prefix [{JsonRpcConstants.ReservedMethodPrefix}]");
            }

            KnownRoutes.Add(key, methodMetadata);
        }