public async Task When_query_parameter_is_enum_array_then_the_enum_is_referenced() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings { DefaultUrlTemplate = "api/{controller}/{action}/{id}", DefaultEnumHandling = EnumHandling.String, DefaultPropertyNameHandling = PropertyNameHandling.Default, SchemaType = SchemaType.Swagger2, }; var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllerAsync <FooController>(); var json = document.ToJson(); var gen = new SwaggerToTypeScriptClientGenerator(document, new SwaggerToTypeScriptClientGeneratorSettings { Template = TypeScriptTemplate.JQueryCallbacks }); var code = gen.GenerateFile(); //// Assert Assert.IsNotNull(document.Operations.First().Operation.Parameters.First().Item.SchemaReference); Assert.IsTrue(code.Contains("getFoos(bars: Bar[], ")); }
public async Task When_redundant_attributes_are_available_then_output_is_correct() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings { TypeMappers = { new ObjectTypeMapper(typeof(JsonDate), new JsonSchema4 { Type = JsonObjectType.String, Format = "date" }) }, AddMissingPathParameters = false, NullHandling = NullHandling.Swagger, GenerateKnownTypes = true, FlattenInheritanceHierarchy = true, DefaultEnumHandling = EnumHandling.String, IsAspNetCore = false, }; var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllerAsync <MyController>(); var json = document.ToJson(); //// Assert Assert.IsTrue(json.Contains("\"$ref\": \"#/definitions/LockedFlight\"")); }
private async Task <SwaggerDocument> GetSwaggerDocument() { // Workaround: NSwag semm to have a bug in enum handling void editEnumType(JsonSchema4 type) { if (type.IsEnumeration && type.Type == JsonObjectType.None) { type.Type = JsonObjectType.Integer; } foreach (var t in type.Properties.Values) { editEnumType(t); } } // var d = await SwaggerDocument.FromFileAsync("c:/users/exyi/Downloads/github-swagger.json"); var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); var controllers = typeof(GeneratorViewModel) .GetTypeInfo() .Assembly.GetTypes() .Where(t => typeof(Controller).IsAssignableFrom(t)); var d = await generator.GenerateForControllersAsync(controllers); this.PopulateOperationIds(d); foreach (var t in d.Definitions.Values) { editEnumType(t); } return(d); }
public IActionResult Generate() { var settings = new WebApiToSwaggerGeneratorSettings { DefaultUrlTemplate = "api/{controller}/{action}/{id}", DefaultPropertyNameHandling = PropertyNameHandling.CamelCase }; var generator = new WebApiToSwaggerGenerator(settings); var controllers = typeof(Ng2GenerateController).GetTypeInfo().Assembly.GetTypes() .Where(t => typeof(Controller).IsAssignableFrom(t)) .ToList(); var document = generator.GenerateForControllers(controllers); //var json = document.ToJson(); //return Content(document.ToJson()); var typescriptGeneratorSettings = new SwaggerToTypeScriptClientGeneratorSettings() { ClassName = "{controller}Client", Template = TypeScriptTemplate.Angular2, GenerateClientClasses = true, GenerateClientInterfaces = true, GenerateDtoTypes = true, TypeScriptGeneratorSettings = new TypeScriptGeneratorSettings() { TypeStyle = TypeScriptTypeStyle.Interface, //TypeNameGenerator = new MyTypeNameGenerator(), } }; var tsGenerator = new SwaggerToTypeScriptClientGenerator(document, typescriptGeneratorSettings); var typescript = tsGenerator.GenerateFile(); typescript = @" // this is file generated by hitting the /swagger/ng2 endpoint " + typescript; // hack! typescript = typescript.Replace("return <Observable<any>><any>Observable.throw(e);", "return <Observable<any>><any>Observable.throw(response);"); typescript = typescript.Replace("return <Observable<UserProfileVm>><any>Observable.throw(e)", "return <Observable<any>><any>Observable.throw(response)"); // write typescript to file under ng app var webRoot = _env.WebRootPath; var file = System.IO.Path.Combine(webRoot, @"..\ClientApp\app\Right4MeClient.ts"); System.IO.File.WriteAllText(file, typescript); return(Content(typescript)); }
/// <summary>Processes the specified method information.</summary> /// <param name="context"></param> /// <returns>true if the operation should be added to the Swagger specification.</returns> public bool Process(OperationProcessorContext context, WebApiToSwaggerGeneratorSettings setting) { ProcessSwaggerTagsAttribute(context.Document, context.OperationDescription, context.MethodInfo); ProcessSwaggerTagAttributes(context.Document, context.OperationDescription, context.MethodInfo); if (!context.OperationDescription.Operation.Tags.Any()) { context.OperationDescription.Operation.Tags.Add(context.MethodInfo.DeclaringType.Name); } return(true); }
/// <summary>Processes the specified method information.</summary> /// <param name="context"></param> /// <param name="setting"></param> /// <returns>true if the operation should be added to the Swagger specification.</returns> public bool Process(OperationProcessorContext context, WebApiToSwaggerGeneratorSettings setting) { var summaryAttrSplits = setting.SummaryAttribute.Split('.'); var attrName = ""; var prop = ""; if (summaryAttrSplits.Length > 1) { attrName = summaryAttrSplits[0]; prop = summaryAttrSplits[1]; } else { attrName = setting.SummaryAttribute; } dynamic descriptionAttribute = context.MethodInfo.GetCustomAttributes() .SingleOrDefault(a => a.GetType().Name == attrName); if (descriptionAttribute != null) { if (!string.IsNullOrEmpty(prop)) { if (descriptionAttribute.GetType().GetProperty(prop) == null) { throw new Exception($"类{attrName}不存在该属性{prop}"); } context.OperationDescription.Operation.Summary = descriptionAttribute.GetType().GetProperty(prop).GetValue(descriptionAttribute, null); } } else { var summary = context.MethodInfo.GetXmlSummary(); if (summary != string.Empty) { context.OperationDescription.Operation.Summary = summary; } } if (string.IsNullOrEmpty(context.OperationDescription.Operation.Summary)) { context.OperationDescription.Operation.Summary = context.MethodInfo.Name; } var remarks = context.MethodInfo.GetXmlRemarks(); if (remarks != string.Empty) { context.OperationDescription.Operation.Description = remarks; } return(true); }
private async Task <SwaggerDocument> GetSwaggerDocument() { var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); var controllers = typeof(GeneratorViewModel) .GetTypeInfo() .Assembly.GetTypes() .Where(t => typeof(Controller).IsAssignableFrom(t)); return(await generator.GenerateForControllersAsync(controllers)); }
public async Task When_custom_operation_processor_is_added_via_attribute_then_it_is_processed() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllerAsync <TestController>(); //// Assert Assert.IsTrue(document.Operations.First().Operation.ExtensionData.ContainsKey("x-code-samples")); Assert.AreEqual(2, ((IList)document.Operations.First().Operation.ExtensionData["x-code-samples"]).Count); }
public async Task When_no_IncludedVersions_are_defined_then_all_routes_are_available_and_replaced() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllerAsync <TestController>(); //// Assert Assert.IsTrue(document.Operations.First().Operation.ExtensionData.ContainsKey("x-code-samples")); Assert.AreEqual(2, ((IList)document.Operations.First().Operation.ExtensionData["x-code-samples"]).Count); }
public async Task GenerateSwagger() { var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); var controllers = typeof(GeneratorViewModel) .GetTypeInfo() .Assembly.GetTypes() .Where(t => typeof(Controller).IsAssignableFrom(t)); var d = await generator.GenerateForControllersAsync(controllers); Context.ReturnFile(Encoding.UTF8.GetBytes(d.ToJson()), "WebApi.swagger.json", "text/json"); }
public async Task When_SwaggerResponseAttribute_is_on_class_then_it_is_applied_to_all_methods() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllerAsync <MyController>(); var json = document.ToJson(); //// Assert Assert.IsTrue(document.Operations.First().Operation.Responses.ContainsKey("403")); }
private async Task <SwaggerDocument> GetSwaggerDocument() { return(await SwaggerDocument.FromFileAsync("c:/users/exyi/Downloads/github-swagger.json")); var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); var controllers = typeof(GeneratorViewModel) .GetTypeInfo() .Assembly.GetTypes() .Where(t => typeof(Controller).IsAssignableFrom(t)); return(await generator.GenerateForControllersAsync(controllers)); }
/// <summary>Processes the specified method information.</summary> /// <param name="context"></param> /// <returns>true if the operation should be added to the Swagger specification.</returns> public bool Process(OperationProcessorContext context, WebApiToSwaggerGeneratorSettings setting) { if (context.OperationDescription.Operation.Security == null) { context.OperationDescription.Operation.Security = new List <SwaggerSecurityRequirement>(); } var scopes = GetScopes(context.OperationDescription, context.MethodInfo); context.OperationDescription.Operation.Security.Add(new SwaggerSecurityRequirement { { _name, scopes } }); return(true); }
public async Task When_swagger_spec_is_generated_then_no_route_problem_is_detected() { /// Arrange var settings = new WebApiToSwaggerGeneratorSettings { DefaultUrlTemplate = "{controller}/{id}", AddMissingPathParameters = false, }; /// Act var generator = new WebApiToSwaggerGenerator(settings); var document = await generator.GenerateForControllerAsync <ProductsController>(); var swaggerSpecification = document.ToJson(); /// Assert Assert.IsNotNull(swaggerSpecification); }
public void When_query_parameter_is_enum_array_then_the_enum_is_referenced() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings { DefaultUrlTemplate = "api/{controller}/{action}/{id}", DefaultEnumHandling = EnumHandling.String, DefaultPropertyNameHandling = PropertyNameHandling.Default, NullHandling = NullHandling.Swagger }; var generator = new SwaggerGenerators.WebApi.WebApiToSwaggerGenerator(settings); //// Act var service = generator.GenerateForController <FooController>(); var json = service.ToJson(); //// Assert Assert.IsNotNull(service.Operations.First().Operation.Parameters.First().Schema.SchemaReference); }
static void Main(string[] args) { var swaggerSettings = new WebApiToSwaggerGeneratorSettings { DefaultPropertyNameHandling = NJsonSchema.PropertyNameHandling.CamelCase, DefaultUrlTemplate = "api/v0.1/{controller}/{id}", GenerateKnownTypes = true, TypeNameGenerator = new DefaultTypeNameGenerator(), }; var swaggerGenerator = new WebApiToSwaggerGenerator(swaggerSettings); var document = swaggerGenerator.GenerateForController <Controllers.CountriesController>(); string json = document.ToJson(); Console.WriteLine(json); System.IO.File.WriteAllText("CFlowSwagger.json", json); Console.ReadKey(); }
public async Task When_IncludedVersions_are_set_then_only_these_are_available_in_document() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings(); settings.OperationProcessors.Get <ApiVersionProcessor>().IncludedVersions.Add("1"); var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllersAsync(new List <Type> { typeof(VersionedControllerV1), typeof(VersionedControllerV2) }); //// Assert Assert.AreEqual(2, document.Paths.Count); Assert.IsTrue(document.Paths.ContainsKey("/api/v1/foo")); Assert.IsTrue(document.Paths.ContainsKey("/api/v1/bar")); }
public async Task When_no_IncludedVersions_are_defined_then_all_routes_are_available_and_replaced() { //// Arrange var settings = new WebApiToSwaggerGeneratorSettings(); var generator = new WebApiToSwaggerGenerator(settings); //// Act var document = await generator.GenerateForControllersAsync(new List <Type> { typeof(VersionedControllerV1), typeof(VersionedControllerV2) }); //// Assert Assert.AreEqual(4, document.Paths.Count); Assert.IsTrue(document.Paths.ContainsKey("/api/v1/foo")); Assert.IsTrue(document.Paths.ContainsKey("/api/v1/bar")); Assert.IsTrue(document.Paths.ContainsKey("/api/v2/foo")); Assert.IsTrue(document.Paths.ContainsKey("/api/v2/bar")); }
static void Main(string[] args) { var controllers = Metadata.GetAllControllers(); var swagDocSettings = new WebApiToSwaggerGeneratorSettings { DefaultUrlTemplate = "api/{controller}/{action}/{id}" }; var swagDocGenerator = new WebApiToSwaggerGenerator(swagDocSettings); var document = swagDocGenerator.GenerateForControllersAsync(controllers).Result; var codeGenSettings = new SwaggerToTypeScriptClientGeneratorSettings { Template = TypeScriptTemplate.Fetch, PromiseType = PromiseType.Promise, GenerateClientInterfaces = true }; var generator = new SwaggerToTypeScriptClientGenerator(document, codeGenSettings); var code = generator.GenerateFile(); code = code.RemoveStatusCodeHandling(); code = code.AddReferencedTypes(); code = code.WithCustomReplacements(); string outputPath = string.Empty; var directory = ConfigurationManager.AppSettings["OutputDirectory"].ToString(); directory = directory.EndsWith("\\", System.StringComparison.InvariantCultureIgnoreCase) ? directory : directory + "\\"; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } outputPath = directory + "ApiClient.ts"; File.WriteAllText(outputPath, code); }
/// <summary>Initializes a new instance of the <see cref="OperationParameterProcessor"/> class.</summary> /// <param name="settings">The settings.</param> public OperationResponseProcessor(WebApiToSwaggerGeneratorSettings settings) { _settings = settings; }
/// <summary>Initializes a new instance of the <see cref="OperationParameterProcessor"/> class.</summary> /// <param name="settings">The settings.</param> public OperationParameterProcessor(WebApiToSwaggerGeneratorSettings settings) { _settings = settings; }
/// <summary>Processes the specified method information.</summary> /// <param name="context"></param> /// <returns>true if the operation should be added to the Swagger specification.</returns> public bool Process(OperationProcessorContext context, WebApiToSwaggerGeneratorSettings setting) { var httpPath = context.OperationDescription.Path; var parameters = context.MethodInfo.GetParameters().ToList(); 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 = context.SwaggerGenerator.CreatePrimitiveParameter(parameter.Name, parameter); operationParameter.Kind = SwaggerParameterKind.Path; operationParameter.IsNullableRaw = false; operationParameter.IsRequired = true; // Path is always required => property not needed context.OperationDescription.Operation.Parameters.Add(operationParameter); } else { var parameterInfo = JsonObjectTypeDescription.FromType(parameter.ParameterType, parameter.GetCustomAttributes(), _settings.DefaultEnumHandling); if (TryAddFileParameter(parameterInfo, context.OperationDescription.Operation, parameter, context.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, context.OperationDescription.Operation, context.SwaggerGenerator); } else { AddPrimitiveParametersFromUri(uriParameterName, context.OperationDescription.Operation, parameter, parameterInfo, context.SwaggerGenerator); } } else { if (fromBodyAttribute != null) { AddBodyParameter(bodyParameterName, parameter, context.OperationDescription.Operation, context.SwaggerGenerator); } else { AddPrimitiveParameter(uriParameterName, context.OperationDescription.Operation, parameter, context.SwaggerGenerator); } } } } } if (_settings.AddMissingPathParameters) { foreach (Match match in Regex.Matches(httpPath, "{(.*?)(:(.*?))?}")) { var parameterName = match.Groups[1].Value; if (context.OperationDescription.Operation.Parameters.All(p => p.Name != parameterName)) { var parameterType = match.Groups.Count == 4 ? match.Groups[3].Value : "string"; var operationParameter = context.SwaggerGenerator.CreatePathParameter(parameterName, parameterType); context.OperationDescription.Operation.Parameters.Add(operationParameter); } } } RemoveUnusedPathParameters(context.OperationDescription, httpPath); UpdateConsumedTypes(context.OperationDescription); EnsureSingleBodyParameter(context.OperationDescription); return(true); }
/// <summary>Processes the specified method information.</summary> /// <param name="context"></param> /// <returns>true if the operation should be added to the Swagger specification.</returns> public bool Process(OperationProcessorContext context, WebApiToSwaggerGeneratorSettings setting) { var successXmlDescription = context.MethodInfo.ReturnParameter.GetXmlDocumentation() ?? string.Empty; var responseTypeAttributes = context.MethodInfo.GetCustomAttributes() .Where(a => a.GetType().Name == "ResponseTypeAttribute" || a.GetType().Name == "SwaggerResponseAttribute") .ToList(); var producesResponseTypeAttributes = context.MethodInfo.GetCustomAttributes() .Where(a => a.GetType().Name == "ProducesResponseTypeAttribute") .ToList(); if (responseTypeAttributes.Any() || producesResponseTypeAttributes.Any()) { foreach (var attribute in responseTypeAttributes) { dynamic responseTypeAttribute = attribute; var attributeType = attribute.GetType(); var returnType = typeof(void); if (attributeType.GetRuntimeProperty("ResponseType") != null) { returnType = responseTypeAttribute.ResponseType; } else if (attributeType.GetRuntimeProperty("Type") != null) { returnType = responseTypeAttribute.Type; } if (returnType == null) { returnType = typeof(void); } var httpStatusCode = IsVoidResponse(returnType) ? GetVoidResponseStatusCode() : "200"; if (attributeType.GetRuntimeProperty("HttpStatusCode") != null && responseTypeAttribute.HttpStatusCode != null) { httpStatusCode = responseTypeAttribute.HttpStatusCode.ToString(); } else if (attributeType.GetRuntimeProperty("StatusCode") != null && responseTypeAttribute.StatusCode != null) { httpStatusCode = responseTypeAttribute.StatusCode.ToString(); } var description = HttpUtilities.IsSuccessStatusCode(httpStatusCode) ? successXmlDescription : string.Empty; if (attributeType.GetRuntimeProperty("Description") != null) { if (!string.IsNullOrEmpty(responseTypeAttribute.Description)) { description = responseTypeAttribute.Description; } } var typeDescription = JsonObjectTypeDescription.FromType(returnType, context.MethodInfo.ReturnParameter?.GetCustomAttributes(), _settings.DefaultEnumHandling); var response = new SwaggerResponse { Description = description ?? string.Empty }; if (IsVoidResponse(returnType) == false) { response.IsNullableRaw = typeDescription.IsNullable; response.Schema = context.SwaggerGenerator.GenerateAndAppendSchemaFromType(returnType, typeDescription.IsNullable, null); } context.OperationDescription.Operation.Responses[httpStatusCode] = response; } foreach (dynamic producesResponseTypeAttribute in producesResponseTypeAttributes) { var returnType = producesResponseTypeAttribute.Type; var typeDescription = JsonObjectTypeDescription.FromType(returnType, context.MethodInfo.ReturnParameter?.GetCustomAttributes(), _settings.DefaultEnumHandling); var httpStatusCode = producesResponseTypeAttribute.StatusCode.ToString(CultureInfo.InvariantCulture); var response = new SwaggerResponse { Description = HttpUtilities.IsSuccessStatusCode(httpStatusCode) ? successXmlDescription : string.Empty }; if (IsVoidResponse(returnType) == false) { response.IsNullableRaw = typeDescription.IsNullable; response.Schema = context.SwaggerGenerator.GenerateAndAppendSchemaFromType(returnType, typeDescription.IsNullable, null); } context.OperationDescription.Operation.Responses[httpStatusCode] = response; } } else { LoadDefaultSuccessResponse(context.OperationDescription.Operation, context.MethodInfo, successXmlDescription, context.SwaggerGenerator); } return(true); }
/// <summary>Initializes a new instance of the <see cref="WebApiToSwaggerCommand"/> class.</summary> public WebApiToSwaggerCommand() { Settings = new WebApiToSwaggerGeneratorSettings(); ControllerNames = new string[] { }; }
/// <summary>Initializes a new instance of the <see cref="OperationParameterProcessor"/> class.</summary> /// <param name="settings">The settings.</param> public OperationParameterProcessor(WebApiToSwaggerGeneratorSettings settings) { _settings = settings; }