/// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> private void LoadParameters(SwaggerOperation operation, List <ParameterInfo> parameters, string httpPath, SwaggerGenerator swaggerGenerator) { // TODO: Also check other attributes (e.g. FromHeader, ...) // https://docs.asp.net/en/latest/mvc/models/model-binding.html#customize-model-binding-behavior-with-attributes foreach (var parameter in parameters.Where(p => p.ParameterType != typeof(CancellationToken) && p.GetCustomAttributes().All(a => a.GetType().Name != "FromServicesAttribute") && p.GetCustomAttributes().All(a => a.GetType().Name != "BindNeverAttribute"))) { var nameLower = parameter.Name.ToLowerInvariant(); if (httpPath.ToLowerInvariant().Contains("{" + nameLower + "}") || httpPath.ToLowerInvariant().Contains("{" + nameLower + ":")) // path parameter { var operationParameter = swaggerGenerator.CreatePrimitiveParameter(parameter.Name, parameter); operationParameter.Kind = SwaggerParameterKind.Path; operationParameter.IsNullableRaw = false; operationParameter.IsRequired = true; // Path is always required => property not needed operation.Parameters.Add(operationParameter); } else { var parameterInfo = JsonObjectTypeDescription.FromType(parameter.ParameterType, parameter.GetCustomAttributes(), Settings.DefaultEnumHandling); if (TryAddFileParameter(parameterInfo, operation, parameter, swaggerGenerator) == false) { dynamic fromBodyAttribute = parameter.GetCustomAttributes() .SingleOrDefault(a => a.GetType().Name == "FromBodyAttribute"); dynamic fromUriAttribute = parameter.GetCustomAttributes() .SingleOrDefault(a => a.GetType().Name == "FromUriAttribute" || a.GetType().Name == "FromQueryAttribute"); var bodyParameterName = TryGetStringPropertyValue(fromBodyAttribute, "Name") ?? parameter.Name; var uriParameterName = TryGetStringPropertyValue(fromUriAttribute, "Name") ?? parameter.Name; if (parameterInfo.IsComplexType) { if (fromBodyAttribute != null || (fromUriAttribute == null && Settings.IsAspNetCore == false)) { AddBodyParameter(bodyParameterName, parameter, operation, swaggerGenerator); } else { AddPrimitiveParametersFromUri(uriParameterName, operation, parameter, parameterInfo, swaggerGenerator); } } else { if (fromBodyAttribute != null) { AddBodyParameter(bodyParameterName, parameter, operation, swaggerGenerator); } else { AddPrimitiveParameter(uriParameterName, operation, parameter, swaggerGenerator); } } } } } if (Settings.AddMissingPathParameters) { foreach (Match match in Regex.Matches(httpPath, "{(.*?)(:(.*?))?}")) { var parameterName = match.Groups[1].Value; if (operation.Parameters.All(p => p.Name != parameterName)) { var parameterType = match.Groups.Count == 4 ? match.Groups[3].Value : "string"; var operationParameter = swaggerGenerator.CreatePathParameter(parameterName, parameterType); operation.Parameters.Add(operationParameter); } } } if (operation.ActualParameters.Any(p => p.Type == JsonObjectType.File)) { operation.Consumes = new List <string> { "multipart/form-data" } } ; if (operation.ActualParameters.Count(p => p.Kind == SwaggerParameterKind.Body) > 1) { throw new InvalidOperationException("The operation '" + operation.OperationId + "' has more than one body parameter."); } }