public DocumentFilterContext( ApiDescriptionGroupCollection apiDescriptionsGroups, ISchemaRegistry schemaRegistry) { ApiDescriptionsGroups = apiDescriptionsGroups; SchemaRegistry = schemaRegistry; }
private Operation CreateOperation(ApiDescription apiDescription, ISchemaRegistry schemaRegistry) { var groupName = _options.GroupNameSelector(apiDescription); var parameters = apiDescription.ParameterDescriptions .Where(paramDesc => paramDesc.Source.IsFromRequest) .Select(paramDesc => CreateParameter(paramDesc, schemaRegistry)) .ToList(); var responses = new Dictionary<string, Response>(); if (apiDescription.ResponseType == typeof(void)) responses.Add("204", new Response { Description = "No Content" }); else responses.Add("200", CreateSuccessResponse(apiDescription.ResponseType, schemaRegistry)); var operation = new Operation { Tags = (groupName != null) ? new[] { groupName } : null, OperationId = apiDescription.ActionDescriptor.DisplayName, Produces = apiDescription.Produces().ToList(), //consumes = apiDescription.Consumes().ToList(), Parameters = parameters.Any() ? parameters : null, // parameters can be null but not empty Responses = responses, Deprecated = apiDescription.IsObsolete() }; var filterContext = new OperationFilterContext(apiDescription, schemaRegistry); foreach (var filter in _options.OperationFilters) { filter.Apply(operation, filterContext); } return operation; }
public ModelFilterContext( Type systemType, JsonObjectContract jsonObjectContract, ISchemaRegistry schemaRegistry) { SystemType = systemType; JsonObjectContract = jsonObjectContract; SchemaRegistry = schemaRegistry; }
private PathItem CreatePathItem(IEnumerable<ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); // Group further by http method var perMethodGrouping = apiDescriptions .GroupBy(apiDesc => apiDesc.HttpMethod); foreach (var group in perMethodGrouping) { var httpMethod = group.Key; if (httpMethod == null) throw new NotSupportedException(string.Format( "Unbounded HTTP verbs for path '{0}'. Are you missing an HttpMethodAttribute?", group.First().RelativePathSansQueryString())); if (group.Count() > 1) throw new NotSupportedException(string.Format( "Multiple operations with path '{0}' and method '{1}'. Are you overloading action methods?", group.First().RelativePathSansQueryString(), httpMethod)); var apiDescription = group.Single(); switch (httpMethod) { case "GET": pathItem.Get = CreateOperation(apiDescription, schemaRegistry); break; case "PUT": pathItem.Put = CreateOperation(apiDescription, schemaRegistry); break; case "POST": pathItem.Post = CreateOperation(apiDescription, schemaRegistry); break; case "DELETE": pathItem.Delete = CreateOperation(apiDescription, schemaRegistry); break; case "OPTIONS": pathItem.Options = CreateOperation(apiDescription, schemaRegistry); break; case "HEAD": pathItem.Head = CreateOperation(apiDescription, schemaRegistry); break; case "PATCH": pathItem.Patch = CreateOperation(apiDescription, schemaRegistry); break; } } return pathItem; }
private void ApplyResponsesFrom( Operation operation, IOrderedEnumerable<SwaggerResponseAttribute> attributes, ISchemaRegistry schemaRegistry) { foreach (var attr in attributes) { var statusCode = attr.StatusCode.ToString(); operation.Responses[statusCode] = new Response { Description = attr.Description ?? InferDescriptionFrom(statusCode), Schema = (attr.Type != null) ? schemaRegistry.GetOrRegister(attr.Type) : null }; } }
private Response CreateSuccessResponse(Type responseType, ISchemaRegistry schemaRegistry) { return new Response { Description = "OK", Schema = (responseType != null) ? schemaRegistry.GetOrRegister(responseType) : null }; }
private IParameter CreateParameter(ApiParameterDescription paramDesc, ISchemaRegistry schemaRegistry) { var source = paramDesc.Source.Id.ToLower(); var schema = (paramDesc.Type == null) ? null : schemaRegistry.GetOrRegister(paramDesc.Type); if (source == "body") { return new BodyParameter { Name = paramDesc.Name, In = source, Schema = schema }; } else { var nonBodyParam = new NonBodyParameter { Name = paramDesc.Name, In = source, Required = (source == "path") }; if (schema == null) nonBodyParam.Type = "string"; else nonBodyParam.PopulateFrom(schema); if (nonBodyParam.Type == "array") nonBodyParam.CollectionFormat = "multi"; return nonBodyParam; } }
private PathItem CreatePathItem(IEnumerable<ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); // Group further by http method var perMethodGrouping = apiDescriptions .GroupBy(apiDesc => apiDesc.HttpMethod.ToLower()); foreach (var group in perMethodGrouping) { var httpMethod = group.Key; if (group.Count() > 1) throw new NotSupportedException(string.Format( "Not supported by Swagger 2.0: Multiple operations with path '{0}' and method '{1}'.", group.First().RelativePathSansQueryString(), httpMethod)); var apiDescription = group.Single(); switch (httpMethod) { case "get": pathItem.Get = CreateOperation(apiDescription, schemaRegistry); break; case "put": pathItem.Put = CreateOperation(apiDescription, schemaRegistry); break; case "post": pathItem.Post = CreateOperation(apiDescription, schemaRegistry); break; case "delete": pathItem.Delete = CreateOperation(apiDescription, schemaRegistry); break; case "options": pathItem.Options = CreateOperation(apiDescription, schemaRegistry); break; case "head": pathItem.Head = CreateOperation(apiDescription, schemaRegistry); break; case "patch": pathItem.Patch = CreateOperation(apiDescription, schemaRegistry); break; } } return pathItem; }
private IParameter CreateParameter(ApiParameterDescription paramDesc, ISchemaRegistry schemaRegistry) { var source = paramDesc.Source.Id.ToLower(); var schema = (paramDesc.Type != null) ? schemaRegistry.GetOrRegister(paramDesc.Type) : null; if (source == "body") { return new BodyParameter { Name = paramDesc.Name, In = source, Required = paramDesc.IsRequired(), Schema = schema }; } else { var nonBodyParam = new NonBodyParameter { Name = paramDesc.Name, In = source, Required = paramDesc.IsRequired() }; if (schema != null) nonBodyParam.PopulateFrom(schema); return nonBodyParam; } }
private IList <IParameter> CreateParameters(ServiceEntry serviceEntry, MethodInfo methodInfo, ISchemaRegistry schemaRegistry) { ParameterInfo[] parameterInfo = null; if (methodInfo != null) { parameterInfo = methodInfo.GetParameters(); } ; return(parameterInfo != null && parameterInfo.Any(p => !UtilityType.ConvertibleType.GetTypeInfo().IsAssignableFrom(p.ParameterType) && p.ParameterType.Name != "HttpFormCollection") ? new List <IParameter> { CreateServiceKeyParameter() }.Union(parameterInfo.Select(p => CreateBodyParameter(p, schemaRegistry))).ToList() : new List <IParameter> { CreateServiceKeyParameter() }.Union(parameterInfo.Select(p => CreateNonBodyParameter(p, schemaRegistry))).ToList()); }
private Operation CreateOperation(ServiceEntry serviceEntry, MethodInfo methodInfo, ISchemaRegistry schemaRegistry) { var customAttributes = Enumerable.Empty <object>(); if (methodInfo != null) { customAttributes = methodInfo.GetCustomAttributes(true) .Union(methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true)); } var isDeprecated = customAttributes.Any(attr => attr.GetType() == typeof(ObsoleteAttribute)); var operation = new Operation { OperationId = serviceEntry.Descriptor.Id, Parameters = CreateParameters(serviceEntry, methodInfo, schemaRegistry), Deprecated = isDeprecated ? true : (bool?)null, Responses = CreateResponses(serviceEntry, methodInfo, schemaRegistry), Tags = GetTagsFormServiceEntry(serviceEntry) }; var filterContext = new OperationFilterContext( null, schemaRegistry, methodInfo, serviceEntry); foreach (var filter in _options.OperationFilters) { filter.Apply(operation, filterContext); } return(operation); }
private PathItem CreatePathItem( IEnumerable <ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); // Group further by http method var perMethodGrouping = apiDescriptions .GroupBy(apiDesc => apiDesc.HttpMethod); foreach (var group in perMethodGrouping) { var httpMethod = group.Key; if (httpMethod == null) { throw new NotSupportedException(string.Format( "Ambiguous HTTP method for action - {0}. " + "Actions require an explicit HttpMethod binding for Swagger 2.0", group.First().ActionDescriptor.DisplayName)); } if (group.Count() > 1 && _options.ConflictingActionsResolver == null) { throw new NotSupportedException(string.Format( "HTTP method \"{0}\" & path \"{1}\" overloaded by actions - {2}. " + "Actions require unique method/path combination for Swagger 2.0. Use ConflictingActionsResolver as a workaround", httpMethod, group.First().RelativePathSansQueryString(), string.Join(",", group.Select(apiDesc => apiDesc.ActionDescriptor.DisplayName)))); } var apiDescription = (group.Count() > 1) ? _options.ConflictingActionsResolver(group) : group.Single(); switch (httpMethod) { case "GET": pathItem.Get = CreateOperation(apiDescription, schemaRegistry); break; case "PUT": pathItem.Put = CreateOperation(apiDescription, schemaRegistry); break; case "POST": pathItem.Post = CreateOperation(apiDescription, schemaRegistry); break; case "DELETE": pathItem.Delete = CreateOperation(apiDescription, schemaRegistry); break; case "OPTIONS": pathItem.Options = CreateOperation(apiDescription, schemaRegistry); break; case "HEAD": pathItem.Head = CreateOperation(apiDescription, schemaRegistry); break; case "PATCH": pathItem.Patch = CreateOperation(apiDescription, schemaRegistry); break; } } return(pathItem); }
private IParameter CreateNonBodyParameter(ServiceEntry serviceEntry, ParameterInfo parameterInfo, ISchemaRegistry schemaRegistry) { string reg = @"(?<={)[^{}]*(?=})"; var nonBodyParam = new NonBodyParameter { Name = parameterInfo.Name, In = "query", Required = true, }; if (Regex.IsMatch(serviceEntry.RoutePath, reg) && GetParameters(serviceEntry.RoutePath.ToLower()).Contains(parameterInfo.Name.ToLower())) { nonBodyParam.In = "path"; } if (parameterInfo.ParameterType == null) { nonBodyParam.Type = "string"; } else if (typeof(IEnumerable <KeyValuePair <string, StringValues> >).IsAssignableFrom(parameterInfo.ParameterType) && parameterInfo.ParameterType.Name == "HttpFormCollection") { nonBodyParam.Type = "file"; nonBodyParam.In = "formData"; } else { // Retrieve a Schema object for the type and copy common fields onto the parameter var schema = schemaRegistry.GetOrRegister(parameterInfo.ParameterType); // NOTE: While this approach enables re-use of SchemaRegistry logic, it introduces complexity // and constraints elsewhere (see below) and needs to be refactored! if (schema.Ref != null) { // The registry created a referenced Schema that needs to be located. This means it's not neccessarily // exclusive to this parameter and so, we can't assign any parameter specific attributes or metadata. schema = schemaRegistry.Definitions[schema.Ref.Replace("#/definitions/", string.Empty)]; } else { // It's a value Schema. This means it's exclusive to this parameter and so, we can assign // parameter specific attributes and metadata. Yep - it's hacky! schema.Default = (parameterInfo != null && parameterInfo.IsOptional) ? parameterInfo.DefaultValue : null; } nonBodyParam.PopulateFrom(schema); } return(nonBodyParam); }
private PathItem CreatePathItem( IEnumerable <ServiceEntry> serviceEntries, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); foreach (var entry in serviceEntries) { var methodInfo = entry.Type.GetTypeInfo().DeclaredMethods.Where(p => p.Name == entry.MethodName).FirstOrDefault(); var parameterInfo = methodInfo.GetParameters(); if (entry.Methods.Count() == 0) { if (parameterInfo != null && parameterInfo.Any(p => !UtilityType.ConvertibleType.GetTypeInfo().IsAssignableFrom(p.ParameterType))) { pathItem.Post = CreateOperation(entry, methodInfo, schemaRegistry); } else { pathItem.Get = CreateOperation(entry, methodInfo, schemaRegistry); } } else { foreach (var httpMethod in entry.Methods) { switch (httpMethod) { case "GET": pathItem.Get = CreateOperation(entry, methodInfo, schemaRegistry); break; case "PUT": pathItem.Put = CreateOperation(entry, methodInfo, schemaRegistry); break; case "POST": pathItem.Post = CreateOperation(entry, methodInfo, schemaRegistry); break; case "DELETE": pathItem.Delete = CreateOperation(entry, methodInfo, schemaRegistry); break; case "OPTIONS": pathItem.Options = CreateOperation(entry, methodInfo, schemaRegistry); break; case "HEAD": pathItem.Head = CreateOperation(entry, methodInfo, schemaRegistry); break; case "PATCH": pathItem.Patch = CreateOperation(entry, methodInfo, schemaRegistry); break; } } } } return(pathItem); }
private PathItem CreatePathItem(IEnumerable <ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); // Group further by http method var perMethodGrouping = apiDescriptions .GroupBy(apiDesc => apiDesc.HttpMethod); foreach (var group in perMethodGrouping) { var httpMethod = group.Key; if (httpMethod == null) { throw new NotSupportedException(string.Format( "Unbounded HTTP verbs for path '{0}'. Are you missing an HttpMethodAttribute?", group.First().RelativePathSansQueryString())); } if (group.Count() > 1) { throw new NotSupportedException(string.Format( "Multiple operations with path '{0}' and method '{1}'. Are you overloading action methods?", group.First().RelativePathSansQueryString(), httpMethod)); } var apiDescription = group.Single(); switch (httpMethod) { case "GET": pathItem.Get = CreateOperation(apiDescription, schemaRegistry); break; case "PUT": pathItem.Put = CreateOperation(apiDescription, schemaRegistry); break; case "POST": pathItem.Post = CreateOperation(apiDescription, schemaRegistry); break; case "DELETE": pathItem.Delete = CreateOperation(apiDescription, schemaRegistry); break; case "OPTIONS": pathItem.Options = CreateOperation(apiDescription, schemaRegistry); break; case "HEAD": pathItem.Head = CreateOperation(apiDescription, schemaRegistry); break; case "PATCH": pathItem.Patch = CreateOperation(apiDescription, schemaRegistry); break; } } return(pathItem); }
private Response CreateResponse(ServiceEntry apiResponseType, MethodInfo methodInfo, ISchemaRegistry schemaRegistry) { var description = ResponseDescriptionMap .FirstOrDefault((entry) => Regex.IsMatch("200", entry.Key)) .Value; return(new Response { Description = description, Schema = (methodInfo.ReturnType != typeof(Task) && methodInfo.ReturnType != typeof(void)) ? schemaRegistry.GetOrRegister(typeof(HttpResultMessage <>).MakeGenericType(methodInfo.ReturnType.GenericTypeArguments)) : null }); }
public OperationFilterContext(ApiDescription apiDescription, ISchemaRegistry schemaRegistry) { ApiDescription = apiDescription; SchemaRegistry = schemaRegistry; }
private PathItem CreatePathItem(IEnumerable <ApiDescription> apiDescriptions, ISchemaRegistry schemaRegistry) { var pathItem = new PathItem(); // Group further by http method var perMethodGrouping = apiDescriptions .GroupBy(apiDesc => apiDesc.HttpMethod.ToLower()); foreach (var group in perMethodGrouping) { var httpMethod = group.Key; if (group.Count() > 1) { throw new NotSupportedException(string.Format( "Not supported by Swagger 2.0: Multiple operations with path '{0}' and method '{1}'.", group.First().RelativePathSansQueryString(), httpMethod)); } var apiDescription = group.Single(); switch (httpMethod) { case "get": pathItem.Get = CreateOperation(apiDescription, schemaRegistry); break; case "put": pathItem.Put = CreateOperation(apiDescription, schemaRegistry); break; case "post": pathItem.Post = CreateOperation(apiDescription, schemaRegistry); break; case "delete": pathItem.Delete = CreateOperation(apiDescription, schemaRegistry); break; case "options": pathItem.Options = CreateOperation(apiDescription, schemaRegistry); break; case "head": pathItem.Head = CreateOperation(apiDescription, schemaRegistry); break; case "patch": pathItem.Patch = CreateOperation(apiDescription, schemaRegistry); break; } } return(pathItem); }