internal static void AddTagFromSwaggerTagAttribute(SwaggerDocument document, dynamic tagAttribute) { if (document.Tags == null) document.Tags = new List<SwaggerTag>(); var tag = document.Tags.SingleOrDefault(t => t.Name == tagAttribute.Name); if (tag == null) { tag = new SwaggerTag(); document.Tags.Add(tag); } tag.Description = tagAttribute.Description; tag.Name = tagAttribute.Name; if (!string.IsNullOrEmpty(tagAttribute.DocumentationDescription) || !string.IsNullOrEmpty(tagAttribute.DocumentationUrl)) { tag.ExternalDocumentation = new SwaggerExternalDocumentation { Description = tagAttribute.DocumentationDescription, Url = tagAttribute.DocumentationUrl }; } }
internal string GenerateFile(SwaggerDocument document, ClientGeneratorOutputType type) { var clientCode = string.Empty; var operations = GetOperations(document); var clientClasses = new List<string>(); if (BaseSettings.OperationNameGenerator.SupportsMultipleClients) { foreach (var controllerOperations in operations.GroupBy(o => BaseSettings.OperationNameGenerator.GetClientName(document, o.Path, o.HttpMethod, o.Operation))) { var controllerName = controllerOperations.Key; var controllerClassName = GetClassName(controllerOperations.Key); clientCode += GenerateClientClass(controllerName, controllerClassName, controllerOperations.ToList(), type) + "\n\n"; clientClasses.Add(controllerClassName); } } else { var controllerName = string.Empty; var controllerClassName = GetClassName(controllerName); clientCode = GenerateClientClass(controllerName, controllerClassName, operations, type); clientClasses.Add(controllerClassName); } return GenerateFile(clientCode, clientClasses, type) .Replace("\r", string.Empty) .Replace("\n\n\n\n", "\n\n") .Replace("\n\n\n", "\n\n"); }
private void ProcessSwaggerTagsAttribute(SwaggerDocument document, SwaggerOperationDescription operationDescription, MethodInfo methodInfo) { dynamic tagsAttribute = methodInfo .GetCustomAttributes() .SingleOrDefault(a => a.GetType().Name == "SwaggerTagsAttribute"); if (tagsAttribute != null) { var tags = ((string[])tagsAttribute.Tags).ToList(); foreach (var tag in tags) { if (operationDescription.Operation.Tags.All(t => t != tag)) operationDescription.Operation.Tags.Add(tag); if (ObjectExtensions.HasProperty(tagsAttribute, "AddToDocument") && tagsAttribute.AddToDocument) { if (document.Tags == null) document.Tags = new List<SwaggerTag>(); if (document.Tags.All(t => t.Name != tag)) document.Tags.Add(new SwaggerTag { Name = tag }); } } } }
private static void ProcessSwaggerTagsAttribute(SwaggerDocument document, Type controllerType) { dynamic tagsAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .SingleOrDefault(a => a.GetType().Name == "SwaggerTagsAttribute"); if (tagsAttribute != null) { var tags = ((string[])tagsAttribute.Tags) .Select(t => new SwaggerTag { Name = t }) .ToList(); if (tags.Any()) { if (document.Tags == null) document.Tags = new List<SwaggerTag>(); foreach (var tag in tags) { if (document.Tags.All(t => t.Name != tag.Name)) document.Tags.Add(tag); } } } }
public async Task<SwaggerDocument> RunAsync() { var schema = await Task.Run(() => JsonSchema4.FromJson(Schema)); var document = new SwaggerDocument(); var rootSchemaName = string.IsNullOrEmpty(Name) && Regex.IsMatch(schema.Title, "^[a-zA-Z0-9_]*$") ? schema.Title : Name; document.Definitions[rootSchemaName] = schema; return document; }
/// <summary>Initializes a new instance of the <see cref="ClientTemplateModel" /> class.</summary> /// <param name="controllerClassName">Name of the controller.</param> /// <param name="operations">The operations.</param> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> public ClientTemplateModel(string controllerClassName, IList<OperationModel> operations, SwaggerDocument document, SwaggerToTypeScriptClientGeneratorSettings settings) { _settings = settings; _document = document; Class = controllerClassName; Operations = operations; }
/// <summary>Initializes a new instance of the <see cref="SwaggerToCSharpClientGenerator" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> /// <param name="resolver">The resolver.</param> /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception> public SwaggerToCSharpClientGenerator(SwaggerDocument document, SwaggerToCSharpClientGeneratorSettings settings, SwaggerToCSharpTypeResolver resolver) : base(document, settings, resolver) { if (document == null) throw new ArgumentNullException(nameof(document)); Settings = settings; _document = document; }
/// <summary>Initializes a new instance of the <see cref="FileTemplateModel" /> class.</summary> /// <param name="clientCode">The client code.</param> /// <param name="outputType">Type of the output.</param> /// <param name="document">The Swagger document.</param> /// <param name="clientGeneratorBase">The client generator base.</param> /// <param name="settings">The settings.</param> /// <param name="resolver">The resolver.</param> public FileTemplateModel(string clientCode, ClientGeneratorOutputType outputType, SwaggerDocument document, ClientGeneratorBase clientGeneratorBase, SwaggerToCSharpGeneratorSettings settings, SwaggerToCSharpTypeResolver resolver) { _clientCode = clientCode; _outputType = outputType; _document = document; _clientGeneratorBase = clientGeneratorBase; _settings = settings; _resolver = resolver; }
/// <summary>Initializes a new instance of the <see cref="ClientTemplateModel" /> class.</summary> /// <param name="controllerName">Name of the controller.</param> /// <param name="controllerClassName">The class name of the controller.</param> /// <param name="operations">The operations.</param> /// <param name="document">The Swagger document.</param> /// <param name="exceptionSchema">The exception schema.</param> /// <param name="settings">The settings.</param> public ClientTemplateModel(string controllerName, string controllerClassName, IList<OperationModel> operations, SwaggerDocument document, JsonSchema4 exceptionSchema, SwaggerToCSharpClientGeneratorSettings settings) { _document = document; _exceptionSchema = exceptionSchema; _settings = settings; Class = controllerClassName; ExceptionClass = _settings.ExceptionClass.Replace("{controller}", controllerName); Operations = operations; }
private static void ProcessSwaggerTagAttributes(SwaggerDocument document, Type controllerType) { var tagAttributes = controllerType.GetTypeInfo().GetCustomAttributes() .Where(a => a.GetType().Name == "SwaggerTagAttribute") .Select(a => (dynamic)a) .ToArray(); if (tagAttributes.Any()) { foreach (var tagAttribute in tagAttributes) AddTagFromSwaggerTagAttribute(document, tagAttribute); } }
/// <summary>Initializes a new instance of the <see cref="FileTemplateModel" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="clientCode">The client code.</param> /// <param name="clientClasses">The client classes.</param> /// <param name="settings">The settings.</param> /// <param name="extensionCode">The extension code.</param> /// <param name="resolver">The resolver.</param> public FileTemplateModel(SwaggerDocument document, string clientCode, IEnumerable<string> clientClasses, SwaggerToTypeScriptClientGeneratorSettings settings, TypeScriptExtensionCode extensionCode, TypeScriptTypeResolver resolver) { _document = document; _extensionCode = extensionCode; _settings = settings; _resolver = resolver; _clientCode = clientCode; ClientClasses = clientClasses.ToArray(); Types = GenerateDtoTypes(); ExtensionCodeBottom = GenerateExtensionCodeAfter(); }
/// <summary>Initializes a new instance of the <see cref="SwaggerToTypeScriptClientGenerator" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> /// <param name="resolver">The resolver.</param> /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception> public SwaggerToTypeScriptClientGenerator(SwaggerDocument document, SwaggerToTypeScriptClientGeneratorSettings settings, TypeScriptTypeResolver resolver) : base(resolver, settings.CodeGeneratorSettings) { if (document == null) throw new ArgumentNullException(nameof(document)); Settings = settings; _document = document; _resolver = resolver; _resolver.AddGenerators(_document.Definitions); _extensionCode = new TypeScriptExtensionCode( Settings.TypeScriptGeneratorSettings.ExtensionCode, Settings.TypeScriptGeneratorSettings.ExtendedClasses, new[] { Settings.ClientBaseClass }); }
private void ProcessSwaggerTagAttributes(SwaggerDocument document, SwaggerOperationDescription operationDescription, MethodInfo methodInfo) { var tagAttributes = methodInfo.GetCustomAttributes() .Where(a => a.GetType().Name == "SwaggerTagAttribute") .Select(a => (dynamic)a) .ToArray(); if (tagAttributes.Any()) { foreach (var tagAttribute in tagAttributes) { if (operationDescription.Operation.Tags.All(t => t != tagAttribute.Name)) operationDescription.Operation.Tags.Add(tagAttribute.Name); if (ObjectExtensions.HasProperty(tagAttribute, "AddToDocument") && tagAttribute.AddToDocument) DocumentTagsProcessor.AddTagFromSwaggerTagAttribute(document, tagAttribute); } } }
public void When_form_parameters_are_defined_then_MultipartFormDataContent_is_generated() { //// Arrange var document = new SwaggerDocument(); document.Paths["foo/bar"] = new SwaggerOperations { { SwaggerOperationMethod.Post, new SwaggerOperation { Parameters = new List<SwaggerParameter> { new SwaggerParameter { Name = "foo", IsRequired = false, IsNullableRaw = true, Kind = SwaggerParameterKind.FormData, Type = JsonObjectType.String }, new SwaggerParameter { Name = "bar", IsRequired = true, IsNullableRaw = false, Kind = SwaggerParameterKind.FormData, Type = JsonObjectType.String } } } } }; //// Act var generator = new SwaggerToCSharpClientGenerator(document, new SwaggerToCSharpClientGeneratorSettings()); var code = generator.GenerateFile(); //// Assert Assert.IsTrue(code.Contains("new System.Net.Http.MultipartFormDataContent")); Assert.IsTrue(code.Contains("if (foo != null)")); Assert.IsTrue(code.Contains("throw new System.ArgumentNullException(\"bar\");")); }
public void When_generating_operation_id() { //// Arrange var document = new SwaggerDocument(); document.Paths["path"] = new SwaggerOperations { { SwaggerOperationMethod.Get, new SwaggerOperation { } }, { SwaggerOperationMethod.Post, new SwaggerOperation { } } }; //// Act document.GenerateOperationIds(); //// Assert Assert.IsTrue(document.Operations.GroupBy(o => o.Operation.OperationId).All(g => g.Count() == 1)); }
/// <summary>Gets the operation name for a given operation.</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The operation name.</returns> public string GetOperationName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { var clientName = GetClientName(operation); var operationName = GetOperationName(operation); var hasOperationWithSameName = document.Operations .Where(o => o.Operation != operation) .Any(o => GetClientName(o.Operation) == clientName && GetOperationName(o.Operation) == operationName); if (hasOperationWithSameName) { if (operationName.ToLowerInvariant().StartsWith("get")) { var isArrayResponse = operation.Responses.ContainsKey("200") && operation.Responses["200"].Schema != null && operation.Responses["200"].Schema.Type.HasFlag(JsonObjectType.Array); if (isArrayResponse) return "GetAll" + operationName.Substring(3); } } return operationName; }
internal string FromAssemblyType(string[] classNames, string settingsData) { var document = new SwaggerDocument(); var settings = JsonConvert.DeserializeObject<AssemblyTypeToSwaggerGeneratorSettings>(settingsData); RegisterReferencePaths(GetAllReferencePaths(settings)); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new SwaggerSchemaResolver(document, settings); #if FullNet var assembly = Assembly.LoadFrom(settings.AssemblyPath); #else var assembly = Context.LoadFromAssemblyPath(settings.AssemblyPath); #endif foreach (var className in classNames) { var type = assembly.GetType(className); var schema = generator.Generate(type, schemaResolver); document.Definitions[type.Name] = schema; } return document.ToJson(); }
/// <summary>Initializes a new instance of the <see cref="SwaggerToCSharpClientGenerator" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception> public SwaggerToCSharpClientGenerator(SwaggerDocument document, SwaggerToCSharpClientGeneratorSettings settings) : this(document, settings, SwaggerToCSharpTypeResolver.CreateWithDefinitions(settings.CSharpGeneratorSettings, document.Definitions)) { }
/// <summary>Initializes a new instance of the <see cref="SwaggerToTypeScriptClientGenerator" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception> public SwaggerToTypeScriptClientGenerator(SwaggerDocument document, SwaggerToTypeScriptClientGeneratorSettings settings) : this(document, settings, new TypeScriptTypeResolver(settings.TypeScriptGeneratorSettings, document)) { }
/// <summary>Initializes a new instance of the <see cref="SwaggerToCSharpWebApiControllerGenerator" /> class.</summary> /// <param name="document">The Swagger document.</param> /// <param name="settings">The settings.</param> /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception> public SwaggerToCSharpWebApiControllerGenerator(SwaggerDocument document, SwaggerToCSharpWebApiControllerGeneratorSettings settings) : this(document, settings, SwaggerToCSharpTypeResolver.CreateWithDefinitions(settings.CSharpGeneratorSettings, document)) { }
public void When_using_json_schema_with_references_in_service_then_references_are_correctly_resolved() { //// Arrange var jsonSchema = @"{ ""definitions"": { ""app"": { ""definitions"": { ""name"": { ""pattern"": ""^[a-z][a-z0-9-]{3,30}$"", ""type"": ""string"" } }, ""properties"": { ""name"": { ""$ref"": ""#/definitions/app/definitions/name"" } }, ""required"": [""name""], ""type"": ""object"" } }, ""properties"": { ""app"": { ""$ref"": ""#/definitions/app"" }, }, ""type"": ""object"" }"; //// Act var schema = JsonSchema4.FromJson(jsonSchema); var document = new SwaggerDocument(); document.Definitions["Foo"] = schema; //// Assert var jsonService = document.ToJson(); // no exception expected }
public DotvvmSwaggerToTypeScriptClientGenerator(SwaggerDocument document, SwaggerToTypeScriptClientGeneratorSettings settings, TypeScriptTypeResolver resolver) : base(document, settings, resolver) { this.resolver = resolver; }
private static void ResolveReferences(SwaggerDocument document) { void MatchRef(Schema schema) { if (schema == null) { return; } if (schema.Type == "array") { MatchRef(schema.Items); return; } if (string.IsNullOrEmpty(schema.Ref)) { return; } Match match = ReferenceRegex.Match(schema.Ref); if (match.Success) { string name = match.Groups["name"].ToString(); Schema resolved = document.Definitions[name]; SchemaName.Set(resolved, name); ResolvedReference.Set(schema, resolved); } else { throw new ArgumentException($"Ref '{schema.Ref}' not found."); } } foreach ((string defName, Schema scheme) in document.Definitions) { foreach ((string propName, Schema prop) in scheme.Properties) { MatchRef(prop); } } foreach ((string path, PathItem pathItem) in document.Paths) { foreach ((string method, Operation operation) in GetOperations(pathItem)) { if (operation.Parameters != null) { foreach (IParameter parameter in operation.Parameters) { if (parameter is BodyParameter bodyParameter) { MatchRef(bodyParameter.Schema); } } } foreach ((string status, Response response) in operation.Responses) { MatchRef(response.Schema); } } } }
public void When_swagger_contains_optional_parameters_then_they_are_rendered_in_CSharp() { //// Arrange var swagger = @"{ ""paths"":{ ""/journeys"":{ ""get"":{ ""tags"":[ ""CheckIn"" ], ""summary"":""Retrieve journeys"", ""operationId"":""retrieveJourneys"", ""description"":"""", ""parameters"":[ { ""$ref"":""#/parameters/lastName"" }, { ""$ref"":""#/parameters/optionalOrderId"" }, { ""$ref"":""#/parameters/eTicketNumber"" }, { ""$ref"":""#/parameters/optionalFrequentFlyerCardId"" }, { ""$ref"":""#/parameters/optionalDepartureDate"" }, { ""$ref"":""#/parameters/optionalOriginLocationCode"" } ], ""responses"": {} } } }, ""parameters"":{ ""lastName"":{ ""name"":""lastName"", ""type"":""string"", ""required"":true }, ""optionalOrderId"":{ ""name"":""optionalOrderId"", ""type"":""string"", ""required"":false }, ""eTicketNumber"":{ ""name"":""eTicketNumber"", ""type"":""string"", ""required"":false }, ""optionalFrequentFlyerCardId"":{ ""name"":""optionalFrequentFlyerCardId"", ""type"":""string"", ""required"":false }, ""optionalDepartureDate"":{ ""name"":""optionalDepartureDate"", ""type"":""string"", ""required"":false }, ""optionalOriginLocationCode"":{ ""name"":""optionalOriginLocationCode"", ""type"":""string"", ""required"":false } } }"; var document = SwaggerDocument.FromJsonAsync(swagger).Result; //// Act var generator = new SwaggerToCSharpClientGenerator(document, new SwaggerToCSharpClientGeneratorSettings()); var code = generator.GenerateFile(); //// Assert Assert.IsTrue(code.Contains("lastName")); Assert.IsTrue(code.Contains("optionalOrderId")); }
public byte[] BuildSwaggerJson() { try { if (options.XmlDocumentPath != null && !File.Exists(options.XmlDocumentPath)) { xDocLookup = null; } else { xDocLookup = (options.XmlDocumentPath != null) ? BuildXmlMemberCommentStructure(options.XmlDocumentPath) : null; } var doc = new SwaggerDocument(); doc.info = options.Info; doc.host = (options.CustomHost != null) ? options.CustomHost(httpContext) : httpContext.Request.Headers["Host"][0]; doc.basePath = options.ApiBasePath; doc.schemes = (options.ForceSchemas.Length == 0) ? new[] { httpContext.Request.IsHttps ? "https" : httpContext.Request.Scheme } : options.ForceSchemas; doc.paths = new Dictionary <string, PathItem>(); doc.definitions = new Dictionary <string, Schema>(); // tags. var xmlServiceName = (xDocLookup != null) ? BuildXmlTypeSummary(options.XmlDocumentPath) : null; doc.tags = handlers .Select(x => x.DeclaringType.Name) .Distinct() .Select(x => { string desc = null; if (xmlServiceName != null) { xmlServiceName.TryGetValue(x, out desc); } return(new Tag() { name = x, description = desc }); }) .ToArray(); foreach (var item in handlers) { XmlCommentStructure xmlComment = null; if (xDocLookup != null) { xmlComment = xDocLookup[Tuple.Create(item.DeclaringType.Name, item.Name)].FirstOrDefault(); } var parameters = BuildParameters(doc.definitions, xmlComment, item); var operation = new Operation { tags = new[] { item.DeclaringType.Name }, summary = (xmlComment != null) ? xmlComment.Summary : "", description = (xmlComment != null) ? xmlComment.Remarks : "", parameters = parameters, responses = new Dictionary <string, Response> { { "default", new Response { description = "done operation" } }, } }; doc.paths.Add("/" + item.DeclaringType.Name + "/" + item.Name, new PathItem { post = operation }); // everything post. } using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms, new UTF8Encoding(false))) { var serializer = new JsonSerializer() { NullValueHandling = NullValueHandling.Ignore, ContractResolver = IgnoreEmptyEnumerablesResolver.Instance // omit empty collection. }; serializer.Serialize(sw, doc); sw.Flush(); return(ms.ToArray()); } } catch (Exception ex) { return(Encoding.UTF8.GetBytes(ex.ToString())); } }
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { context.SchemaRegistry.GetOrRegister(typeof(DateTime)); swaggerDoc.Extensions.Add("X-property1", "value"); }
/// <summary> /// Applies the specified swagger document. /// </summary> /// <param name="swaggerDoc">The swagger document.</param> /// <param name="schemaRegistry">The schema registry.</param> /// <param name="apiExplorer">The API explorer.</param> public override void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { var paths = swaggerDoc.paths; if (paths == null || !paths.Any()) { return; } var allOperationNames = GetOperationOrder(swaggerDoc, apiExplorer); if (allOperationNames == null || allOperationNames.Length == 0) { OrderingApply(swaggerDoc, schemaRegistry, apiExplorer); return; } var groups = new Dictionary <int, IDictionary <string, PathItem> >(); foreach (var path in paths) { GetInvokeMethod(path.Value, out var tag); var position = allOperationNames.ToList().IndexOf(tag); if (position == -1) { position = int.MaxValue; } IDictionary <string, PathItem> dictionary; if (groups.ContainsKey(position)) { dictionary = groups[position]; dictionary.Add(path.Key, path.Value); } else { dictionary = new Dictionary <string, PathItem> { { path.Key, path.Value } }; groups.Add(position, dictionary); } } groups = ProcessMethodOrdering(groups, apiExplorer); groups = groups.OrderBy(c => c.Key).ToDictionary(c => c.Key, c => c.Value); var result = new Dictionary <string, PathItem>(); foreach (var item in groups) { foreach (var api in item.Value) { result.Add(api.Key, api.Value); } } swaggerDoc.paths = result; }
private static string[] GetOperationOrder(SwaggerDocument swaggerDoc, IApiExplorer apiExplorer) { var paths = swaggerDoc.paths; if (paths == null || !paths.Any()) { return(null); } var attributes = new List <SwaggerOperationOrderAttribute>(); foreach (var path in paths) { var key = GetInvokeMethod(path.Value, out _); var apiKey = $"{key}{path.Key.TrimStart('/')}"; var apiFound = apiExplorer.ApiDescriptions.FirstOrDefault(c => c.ID.StartsWith(apiKey)); var apiDescriptor = apiFound.ActionDescriptor; var controllerDescriptor = apiDescriptor.ControllerDescriptor; var controllerType = controllerDescriptor.ControllerType; var customAttribute = controllerType.GetCustomAttributes(typeof(SwaggerOperationOrderAttribute), true).FirstOrDefault() as SwaggerOperationOrderAttribute ?? controllerType.BaseType.GetCustomAttributes(typeof(SwaggerOperationOrderAttribute), true).FirstOrDefault() as SwaggerOperationOrderAttribute; if (customAttribute == null) { continue; } attributes.Add(customAttribute); } if (!attributes.Any()) { return(null); } var sdk = attributes.FirstOrDefault(c => c.From.Equals(SwaggerOperationOrderAttribute.OperationFrom.Sdk)); var application = attributes.FirstOrDefault(c => c.From.Equals(SwaggerOperationOrderAttribute.OperationFrom.Application)); if (application == null && sdk != null) { return(sdk.OperationTags); } if (sdk == null && application != null) { return(application.OperationTags); } if (application == null) { return(null); } var result = sdk.OperationTags.ToList(); foreach (var cust in application.OperationTags) { if (result.Contains(cust)) { continue; } result.Add(cust); } return(result.ToArray()); }
public static async Task <bool> generateCode(service services, EpicorDetails details) { using (WebClient client = Client.getWebClient(string.IsNullOrEmpty(details.Username) ? "" : details.Username, string.IsNullOrEmpty(details.Password) ? "" : details.Password)) { foreach (var service in services.workspace.collection) { var name = service.href.Replace(".", "").Replace("-", ""); try { string x = client.DownloadString(details.APIURL + service.href); dynamic jsonObj = JsonConvert.DeserializeObject(x); if (!details.APIURL.Contains("baq")) { foreach (var j in jsonObj["paths"]) { var post = j.First["post"]; if (post != null) { var postOpID = j.First["post"]["operationId"]; if (postOpID != null) { j.First["post"]["operationId"] = j.Name.Replace(@"\", "").Replace("/", ""); } } } } string output = JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented); var document = await SwaggerDocument.FromJsonAsync(output); var settings = new SwaggerToCSharpClientGeneratorSettings() { ClassName = name, OperationNameGenerator = new SingleClientFromOperationIdOperationNameGenerator() }; var generator = new SwaggerToCSharpClientGenerator(document, settings); if (details.useBaseClass) { generator.Settings.ClientBaseClass = details.BaseClass; } generator.Settings.UseHttpClientCreationMethod = true; generator.Settings.AdditionalNamespaceUsages = new[] { "Newtonsoft.Json", "Newtonsoft.Json.Linq" }; generator.Settings.GenerateSyncMethods = true; var code = generator.GenerateFile(); code = code //need to replace with my actual namespace .Replace("MyNamespace", details.Namespace + "." + service.href.Replace("-", "")) //Had an error so added but I dont think this replacement is needed for all scenarios, maybe add flag in details later .Replace("var client_ = await CreateHttpClientAsync(cancellationToken).ConfigureAwait(false);", "var client_ = CreateHttpClientAsync(cancellationToken);") //.Replace("var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);", "var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken);") //.Replace("var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false);", "var responseData_ = await response_.Content.ReadAsStringAsync();") //no need .Replace("#pragma warning disable // Disable all warnings", "") //cant use so had to replace .Replace("<Key>k", "Keyk") //cant use so had to replace .Replace("<Value>k", "Valuek") //cant use so had to replace .Replace("_tLСTotalCost", "_tLDTotalCost") //cant use so had to replace .Replace("TLСTotalCost", "TLDTotalCost") //had to change to dictionary<string,jtoken>, additial properties may return a list, parse into jtoken .Replace("private System.Collections.Generic.IDictionary<string, string> _additionalProperties = new System.Collections.Generic.Dictionary<string, string>();", "private System.Collections.Generic.IDictionary<string, JToken> _additionalProperties = new System.Collections.Generic.Dictionary<string, JToken>();") .Replace("public System.Collections.Generic.IDictionary<string, string> AdditionalProperties", " public System.Collections.Generic.IDictionary<string, JToken> AdditionalProperties") //I dont like the required attribute, changed to allow nulls .Replace(", Required = Newtonsoft.Json.Required.Always)]", ", Required = Newtonsoft.Json.Required.AllowNull)]") .Replace("[System.ComponentModel.DataAnnotations.Required]", "") .Replace(@"public string BaseUrl", "public new string BaseUrl") //.Replace("get { return _baseUrl; }", "get;") //.Replace("set { _baseUrl = value; }", "set;"); ; //addReference(details.Project, service.href + ".cs"); File.WriteAllText(Path.GetDirectoryName(details.Project) + "\\" + service.href + ".cs", code); } catch (Exception ex) { Console.WriteLine("{1} : <------> {0}", ex, name); string directory = AppDomain.CurrentDomain.BaseDirectory + @"/Logs/"; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } File.AppendAllText(directory + DateTime.Now.ToString("MMDDYYYY_hhmmssfffff") + ".txt", name + Environment.NewLine + ex); } } } return(true); }
public override async Task GenerateClientAsync(SwaggerDocument document, string documentPath) { await Model.GenerateClientAsync(document, documentPath); TabControl.SelectedIndex = 1; }
/// <summary>Gets the client name for a given operation (may be empty).</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public virtual string GetOperationName(SwaggerDocument document, string path, string httpMethod, SwaggerOperation operation) { return(operation.OperationId); }
/// <summary>Initializes a new instance of the <see cref="AspNetCoreOperationProcessorContext" /> class.</summary> /// <param name="document">The document.</param> /// <param name="operationDescription">The operation description.</param> /// <param name="controllerType">Type of the controller.</param> /// <param name="methodInfo">The method information.</param> /// <param name="swaggerGenerator">The swagger generator.</param> /// <param name="schemaResolver">The schema resolver.</param> /// <param name="allOperationDescriptions">All operation descriptions.</param> /// <param name="schemaGenerator">The schema generator.</param> public AspNetCoreOperationProcessorContext(SwaggerDocument document, SwaggerOperationDescription operationDescription, Type controllerType, MethodInfo methodInfo, SwaggerGenerator swaggerGenerator, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver, IList <SwaggerOperationDescription> allOperationDescriptions) : base(document, operationDescription, controllerType, methodInfo, swaggerGenerator, schemaGenerator, schemaResolver, allOperationDescriptions) { }
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { // Add code generation settings swaggerDoc.info.vendorExtensions.Add("x-ms-code-generation-settings", _settings); }
private static void PassThroughDocumentFilter(SwaggerDocument swaggerDoc, HttpRequest httpRequest) { }
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { // Include the given data type in the final SwaggerDocument // //schemaRegistry.GetOrRegister(typeof(ExtraType)); }
static void Main(string[] args) { bool getMetadata = true; // start by getting secrets. var builder = new ConfigurationBuilder() .AddEnvironmentVariables(); builder.AddUserSecrets <Program>(); var Configuration = builder.Build(); string csdl; // get the metadata. if (getMetadata) { csdl = GetDynamicsMetadata(Configuration); File.WriteAllText("dynamics-metadata.xml", csdl); } else { csdl = File.ReadAllText("dynamics-metadata.xml"); } // fix the csdl. csdl = csdl.Replace("ConcurrencyMode=\"Fixed\"", ""); Microsoft.OData.Edm.IEdmModel model = Microsoft.OData.Edm.Csdl.CsdlReader.Parse(XElement.Parse(csdl).CreateReader()); // fix dates. OpenApiTarget target = OpenApiTarget.Json; OpenApiWriterSettings settings = new OpenApiWriterSettings { BaseUri = new Uri(Configuration["DYNAMICS_ODATA_URI"]) }; string swagger = null; using (MemoryStream ms = new MemoryStream()) { model.WriteOpenApi(ms, target, settings); var buffer = ms.ToArray(); string temp = Encoding.UTF8.GetString(buffer, 0, buffer.Length); // The Microsoft OpenAPI.Net library doesn't seem to work with MS Dynamics metadata, so we use NSwag here. var runner = SwaggerDocument.FromJsonAsync(temp); runner.Wait(); var swaggerDocument = runner.Result; List <string> allops = new List <string>(); Dictionary <string, SwaggerPathItem> itemsToRemove = new Dictionary <string, SwaggerPathItem>(); // fix the operationIds. foreach (var operation in swaggerDocument.Operations) { string suffix = ""; switch (operation.Method) { case SwaggerOperationMethod.Post: suffix = "Create"; // for creates we also want to add a header parameter to ensure we get the new object back. SwaggerParameter swaggerParameter = new SwaggerParameter() { Type = JsonObjectType.String, Name = "Prefer", Default = "return=representation", Description = "Required in order for the service to return a JSON representation of the object.", Kind = SwaggerParameterKind.Header }; operation.Operation.Parameters.Add(swaggerParameter); break; case SwaggerOperationMethod.Patch: suffix = "Update"; break; case SwaggerOperationMethod.Put: suffix = "Put"; break; case SwaggerOperationMethod.Delete: suffix = "Delete"; break; case SwaggerOperationMethod.Get: if (operation.Path.Contains("{")) { suffix = "GetByKey"; } else { suffix = "Get"; } break; } string prefix = "Unknown"; string firstTag = operation.Operation.Tags.FirstOrDefault(); if (firstTag == null) { firstTag = operation.Path.Substring(1); } if (firstTag != null) { bool ok2Delete = true; string firstTagLower = firstTag.ToLower(); if (firstTagLower.Equals("contacts") || firstTagLower.Equals("accounts") || firstTagLower.Equals("invoices") || firstTagLower.Equals("incidents") || firstTagLower.Equals("sharepointsites") || firstTagLower.Equals("savedqueries") || firstTagLower.Equals("sharepointdocumentlocations")) { ok2Delete = false; } if (firstTagLower.IndexOf("spice") != -1) { ok2Delete = false; firstTagLower = firstTagLower.Replace("spice_", ""); firstTagLower = firstTagLower.Replace("spice", ""); operation.Operation.Tags.Clear(); operation.Operation.Tags.Add(firstTagLower); } if (ok2Delete) { if (!itemsToRemove.Keys.Contains(operation.Path)) { itemsToRemove.Add(operation.Path, operation.Operation.Parent); } } if (!allops.Contains(firstTag)) { allops.Add(firstTag); } prefix = firstTagLower; // Capitalize the first character. if (prefix.Length > 0) { prefix.Replace("spice", ""); prefix = ("" + prefix[0]).ToUpper() + prefix.Substring(1); } // remove any underscores. prefix = prefix.Replace("_", ""); } operation.Operation.OperationId = prefix + "_" + suffix; // adjustments to operation parameters foreach (var parameter in operation.Operation.Parameters) { string name = parameter.Name; if (name == null) { name = parameter.ActualParameter.Name; } if (name != null) { if (name == "$top") { parameter.Kind = SwaggerParameterKind.Query; parameter.Reference = null; parameter.Schema = null; parameter.Type = JsonObjectType.Integer; } if (name == "$skip") { parameter.Kind = SwaggerParameterKind.Query; parameter.Reference = null; parameter.Schema = null; parameter.Type = JsonObjectType.Integer; } if (name == "$search") { parameter.Kind = SwaggerParameterKind.Query; parameter.Reference = null; parameter.Schema = null; parameter.Type = JsonObjectType.String; } if (name == "$filter") { parameter.Kind = SwaggerParameterKind.Query; parameter.Reference = null; parameter.Schema = null; parameter.Type = JsonObjectType.String; } if (name == "$count") { parameter.Kind = SwaggerParameterKind.Query; parameter.Reference = null; parameter.Schema = null; parameter.Type = JsonObjectType.Boolean; } if (name == "If-Match") { parameter.Reference = null; parameter.Schema = null; } if (string.IsNullOrEmpty(parameter.Name)) { parameter.Name = name; } } //var parameter = loopParameter.ActualParameter; // get rid of style if it exists. if (parameter.Style != SwaggerParameterStyle.Undefined) { parameter.Style = SwaggerParameterStyle.Undefined; } // clear unique items if (parameter.UniqueItems) { parameter.UniqueItems = false; } // we also need to align the schema if it exists. if (parameter.Schema != null && parameter.Schema.Item != null) { var schema = parameter.Schema; if (schema.Type == JsonObjectType.Array) { // move schema up a level. parameter.Item = schema.Item; parameter.Schema = null; parameter.Reference = null; parameter.Type = JsonObjectType.Array; } if (schema.Type == JsonObjectType.String) { parameter.Schema = null; parameter.Reference = null; parameter.Type = JsonObjectType.String; } } else { // many string parameters don't have the type defined. if (!(parameter.Kind == SwaggerParameterKind.Body) && !parameter.HasReference && (parameter.Type == JsonObjectType.Null || parameter.Type == JsonObjectType.None)) { parameter.Schema = null; parameter.Type = JsonObjectType.String; } } } // adjustments to response foreach (var response in operation.Operation.Responses) { var val = response.Value; if (val != null && val.Reference == null && val.Schema != null) { bool hasValue = false; var schema = val.Schema; foreach (var property in schema.Properties) { if (property.Key.Equals("value")) { hasValue = true; break; } } if (hasValue) { string resultName = operation.Operation.OperationId + "ResponseModel"; if (!swaggerDocument.Definitions.ContainsKey(resultName)) { // move the inline schema to defs. swaggerDocument.Definitions.Add(resultName, val.Schema); val.Schema = new JsonSchema4(); val.Schema.Reference = swaggerDocument.Definitions[resultName]; val.Schema.Type = JsonObjectType.None; } // ODATA - experimental //operation.Operation.ExtensionData.Add ("x-ms-odata", "#/definitions/") } /* * var schema = val.Schema; * * foreach (var property in schema.Properties) * { * if (property.Key.Equals("value")) * { * property.Value.ExtensionData.Add("x-ms-client-flatten", true); * } * } */ } } } foreach (var opDelete in itemsToRemove) { swaggerDocument.Paths.Remove(opDelete); } /* * Cleanup definitions. */ foreach (var definition in swaggerDocument.Definitions) { foreach (var property in definition.Value.Properties) { if (property.Key.Equals("totalamount")) { property.Value.Type = JsonObjectType.Number; property.Value.Format = "decimal"; } if (property.Key.Equals("versionnumber")) { // clear oneof. property.Value.OneOf.Clear(); // force to string. property.Value.Type = JsonObjectType.String; } } } // cleanup parameters. swaggerDocument.Parameters.Clear(); swagger = swaggerDocument.ToJson(SchemaType.Swagger2); // fix up the swagger file. swagger = swagger.Replace("('{", "({"); swagger = swagger.Replace("}')", "})"); swagger = swagger.Replace("\"$ref\": \"#/responses/error\"", "\"schema\": { \"$ref\": \"#/definitions/odata.error\" }"); // fix for problem with the base entity. swagger = swagger.Replace(" {\r\n \"$ref\": \"#/definitions/Microsoft.Dynamics.CRM.crmbaseentity\"\r\n },\r\n", ""); // fix for problem with nullable string arrays. swagger = swagger.Replace(",\r\n \"nullable\": true", ""); // NSwag is almost able to generate the client as well. It does it much faster than AutoRest but unfortunately can't do multiple files yet. // It does generate a single very large file in a few seconds. We don't want a single very large file though as it does not work well with the IDE. // Autorest is used to generate the client using a traditional approach. /* * var generatorSettings = new SwaggerToCSharpClientGeneratorSettings * { * ClassName = "DynamicsClient", * CSharpGeneratorSettings = * { * Namespace = "<namespace>" * } * }; * * var generator = new SwaggerToCSharpClientGenerator(swaggerDocument, generatorSettings); * var code = generator.GenerateFile(); * * File.WriteAllText("<filename>", code); */ } File.WriteAllText("dynamics-swagger.json", swagger); }
/// <summary>Gets the client name for a given operation (may be empty).</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public string GetClientName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { return(GetClientName(operation)); }
/// <summary>Gets the client name for a given operation.</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public string GetClientName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { return GetClientName(operation); }
private async Task <SwaggerDocument> GetSwaggerDocument() { var responseBody = await Client.GetStringAsync("swagger/v1/swagger.json"); return(await SwaggerDocument.FromJsonAsync(responseBody)); }
private static SwaggerDocument CreateService() { var document = new SwaggerDocument(); var settings = new JsonSchemaGeneratorSettings(); var generator = new JsonSchemaGenerator(settings); document.Paths["/Person"] = new SwaggerOperations(); document.Paths["/Person"][SwaggerOperationMethod.Get] = new SwaggerOperation { Responses = new Dictionary<string, SwaggerResponse> { { "200", new SwaggerResponse { Schema = new JsonSchema4 { SchemaReference = generator.Generate(typeof(Person), new SwaggerSchemaResolver(document, settings)) } } } } }; return document; }
/// <summary>Initializes a new instance of the <see cref="SwaggerToCSharpGeneratorBase"/> class.</summary> /// <param name="document">The document.</param> /// <param name="settings">The settings.</param> /// <param name="resolver">The resolver.</param> protected SwaggerToCSharpGeneratorBase(SwaggerDocument document, SwaggerToCSharpGeneratorSettings settings, CSharpTypeResolver resolver) : base(resolver, settings.CodeGeneratorSettings) { _document = document; _settings = settings; }
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Definitions.ToList().ForEach(x => { x.Value.Extensions.Add("$id", $"#/definitions/{x.Key}"); }); }
/// <summary>Gets the client name for a given operation.</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public string GetClientName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { var pathSegments = path.Split('/').Where(p => !p.Contains("{")).Reverse().ToArray(); return pathSegments.Length >= 2 ? pathSegments[1] : string.Empty; }
private static string InjectWrapperClass(string csharpCode, string className, SwaggerDocument document, IOperationNameGenerator nameGenerator, out bool isSinlgeClient, out string clientName) { var clients = document.Operations.Select(o => nameGenerator.GetClientName(document, o.Path, o.Method, o.Operation)).Distinct().ToArray(); if (clients.Length == 1) { isSinlgeClient = true; clientName = clients[0] + "Client"; return(csharpCode); } else { isSinlgeClient = false; clientName = className; var properties = from c in clients let name = ConversionUtilities.ConvertToUpperCamelCase(c, true) let type = name + "Client" select $"public {type} {(string.IsNullOrEmpty(name) ? "Root" : name)} {{ get; set; }}"; var wrapperClass = $@" public class {className} {{ {ConversionUtilities.Tab(string.Join("\n", properties), 1)} }}".Replace("\r\n", "\n"); var namespaceClosing = csharpCode.LastIndexOf('}'); return(csharpCode.Insert(namespaceClosing, ConversionUtilities.Tab(wrapperClass, 1) + "\n")); } }
/// <summary>Gets the client name for a given operation.</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public string GetOperationName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { var pathSegments = path.Split('/').Where(p => !p.Contains("{")).Reverse().ToArray(); return pathSegments.First(); }
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Paths = (IDictionary <string, PathItem>)swaggerDoc.Paths.ToDictionary <KeyValuePair <string, PathItem>, string, PathItem>((Func <KeyValuePair <string, PathItem>, string>)(path => path.Key.Replace("v{version}", swaggerDoc.Info.Version)), (Func <KeyValuePair <string, PathItem>, PathItem>)(path => path.Value)); }
internal SwaggerToCSharpGeneratorBase(SwaggerDocument document, SwaggerToCSharpGeneratorSettings settings, SwaggerToCSharpTypeResolver resolver) : base(resolver, settings.CodeGeneratorSettings) { _document = document; _settings = settings; }
/// <summary>Gets the client name for a given operation (may be empty).</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public virtual string GetClientName(SwaggerDocument document, string path, string httpMethod, SwaggerOperation operation) { return(string.Empty); }
/// <summary>Gets the client name for a given operation.</summary> /// <param name="document">The Swagger document.</param> /// <param name="path">The HTTP path.</param> /// <param name="httpMethod">The HTTP method.</param> /// <param name="operation">The operation.</param> /// <returns>The client name.</returns> public string GetOperationName(SwaggerDocument document, string path, SwaggerOperationMethod httpMethod, SwaggerOperation operation) { return operation.OperationId; }
public void When_parent_parameters_have_same_kind_then_they_are_included() { //// Arrange var swagger = @"{ ""swagger"" : ""2.0"", ""info"" : { ""version"" : ""1.0.2"", ""title"" : ""Test API"" }, ""host"" : ""localhost:8080"", ""basePath"" : ""/"", ""tags"" : [ { ""name"" : ""api"" } ], ""schemes"" : [ ""http"" ], ""paths"" : { ""/removeElement"" : { ""parameters"": [ { ""name"": ""SecureToken"", ""in"": ""header"", ""description"": ""cookie"", ""required"": true, ""type"": ""string"" } ], ""delete"" : { ""tags"" : [ ""api"" ], ""summary"" : ""Removes elements"", ""description"" : ""Removes elements"", ""operationId"" : ""removeElement"", ""consumes"" : [ ""application/json"" ], ""produces"" : [ ""application/json"" ], ""parameters"" : [ { ""name"" : ""X-User"", ""in"" : ""header"", ""description"" : ""User identifier"", ""required"" : true, ""type"" : ""string"" }, { ""name"" : ""elementId"", ""in"" : ""query"", ""description"" : ""The ids of existing elements that should be removed"", ""required"" : false, ""type"" : ""array"", ""items"" : { ""type"" : ""integer"", ""format"" : ""int64"" }, } ], ""responses"" : { ""default"" : { ""description"" : ""successful operation"" } } } } }, ""definitions"" : { } } "; var document = SwaggerDocument.FromJsonAsync(swagger).Result; //// Act var generator = new SwaggerToCSharpClientGenerator(document, new SwaggerToCSharpClientGeneratorSettings()); var code = generator.GenerateFile(); Assert.IsTrue(code.Contains("RemoveElementAsync(string x_User, System.Collections.Generic.IEnumerable<long> elementId, string secureToken)")); }
internal List<OperationModel> GetOperations(SwaggerDocument document) { document.GenerateOperationIds(); var operations = document.Paths .SelectMany(pair => pair.Value.Select(p => new { Path = pair.Key.Trim('/'), HttpMethod = p.Key, Operation = p.Value })) .Select(tuple => { var operation = tuple.Operation; var exceptionSchema = (Resolver as SwaggerToCSharpTypeResolver)?.ExceptionSchema; var responses = operation.Responses.Select(response => new ResponseModel(response, exceptionSchema, this)).ToList(); var defaultResponse = responses.SingleOrDefault(r => r.StatusCode == "default"); if (defaultResponse != null) responses.Remove(defaultResponse); return new OperationModel { Path = tuple.Path, HttpMethod = tuple.HttpMethod, Operation = tuple.Operation, OperationName = BaseSettings.OperationNameGenerator.GetOperationName(document, tuple.Path, tuple.HttpMethod, tuple.Operation), ResultType = GetResultType(operation), HasResultType = HasResultType(operation), ResultDescription = GetResultDescription(operation), ExceptionType = GetExceptionType(operation), HasFormParameters = operation.ActualParameters.Any(p => p.Kind == SwaggerParameterKind.FormData), Responses = responses, DefaultResponse = defaultResponse, Parameters = operation.ActualParameters.Select(p => new ParameterModel( ResolveParameterType(p), operation, p, p.Name, GetParameterVariableName(p), BaseSettings.CodeGeneratorSettings, this)).ToList(), }; }).ToList(); return operations; }
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) => swaggerDoc.Paths = swaggerDoc.Paths .ToDictionary(entry => LowercaseEverythingButParameters(entry.Key), entry => entry.Value);
private static async Task Main(string[] args) { if (args.Length < 2) { Console.Error.WriteLine($"usage {args[0]} path/to/generated"); Environment.Exit(1); } var outputDirectory = args[1]; // Read the spec trimmed // here we cache all name in gen project for later use var swagger = await SwaggerDocument.FromFileAsync(Path.Combine(args[1], "swagger.json")).ConfigureAwait(false); foreach (var(k, v) in swagger.Definitions) { if (v.ExtensionData?.TryGetValue("x-kubernetes-group-version-kind", out var _) == true) { var groupVersionKindElements = (object[])v.ExtensionData["x-kubernetes-group-version-kind"]; var groupVersionKind = (Dictionary <string, object>)groupVersionKindElements[0]; var group = (string)groupVersionKind["group"]; var kind = (string)groupVersionKind["kind"]; var version = (string)groupVersionKind["version"]; ClassNameMap[$"{group}_{kind}_{version}"] = ToPascalCase(k.Replace(".", "")); } } // gen project removed all watch operations, so here we switch back to unprocessed version swagger = await SwaggerDocument.FromFileAsync(Path.Combine(args[1], "swagger.json.unprocessed")).ConfigureAwait(false); _schemaToNameMap = swagger.Definitions.ToDictionary(x => x.Value, x => x.Key); _schemaDefinitionsInMultipleGroups = _schemaToNameMap.Values.Select(x => { var parts = x.Split("."); return(new { FullName = x, Name = parts[parts.Length - 1], Version = parts[parts.Length - 2], Group = parts[parts.Length - 3], }); }) .GroupBy(x => new { x.Name, x.Version }) .Where(x => x.Count() > 1) .SelectMany(x => x) .Select(x => x.FullName) .ToHashSet(); _classNameToPluralMap = swagger.Operations .Where(x => x.Operation.OperationId.StartsWith("list", StringComparison.InvariantCulture)) .Select(x => { return(new { PluralName = x.Path.Split("/").Last(), ClassName = GetClassNameForSchemaDefinition(x.Operation.Responses["200"] .ActualResponseSchema), }); }) .Distinct() .ToDictionary(x => x.ClassName, x => x.PluralName); // dictionary only contains "list" plural maps. assign the same plural names to entities those lists support _classNameToPluralMap = _classNameToPluralMap .Where(x => x.Key.EndsWith("List", StringComparison.InvariantCulture)) .Select(x => new { ClassName = x.Key.Remove(x.Key.Length - 4), PluralName = x.Value }) .ToDictionary(x => x.ClassName, x => x.PluralName) .Union(_classNameToPluralMap) .ToDictionary(x => x.Key, x => x.Value); // Register helpers used in the templating. Helpers.Register(nameof(ToXmlDoc), ToXmlDoc); Helpers.Register(nameof(GetClassName), GetClassName); Helpers.Register(nameof(GetInterfaceName), GetInterfaceName); Helpers.Register(nameof(GetMethodName), GetMethodName); Helpers.Register(nameof(GetDotNetName), GetDotNetName); Helpers.Register(nameof(GetDotNetType), GetDotNetType); Helpers.Register(nameof(GetPathExpression), GetPathExpression); Helpers.Register(nameof(GetGroup), GetGroup); Helpers.Register(nameof(GetApiVersion), GetApiVersion); Helpers.Register(nameof(GetKind), GetKind); Helpers.Register(nameof(GetPlural), GetPlural); Helpers.Register(nameof(GetTuple), GetTuple); // Generate the Watcher operations // We skip operations where the name of the class in the C# client could not be determined correctly. // That's usually because there are different version of the same object (e.g. for deployments). var blacklistedOperations = new HashSet <string>() { }; var watchOperations = swagger.Operations.Where( o => o.Path.Contains("/watch/") && o.Operation.ActualParameters.Any(p => p.Name == "name") && !blacklistedOperations.Contains(o.Operation.OperationId)).ToArray(); // Render. Render.FileToFile("IKubernetes.Watch.cs.template", watchOperations, Path.Combine(outputDirectory, "IKubernetes.Watch.cs")); Render.FileToFile("Kubernetes.Watch.cs.template", watchOperations, Path.Combine(outputDirectory, "Kubernetes.Watch.cs")); // Generate the interface declarations var skippedTypes = new HashSet <string>() { "V1WatchEvent", }; var definitions = swagger.Definitions.Values .Where( d => d.ExtensionData != null && d.ExtensionData.ContainsKey("x-kubernetes-group-version-kind") && !skippedTypes.Contains(GetClassName(d))); var modelsDir = Path.Combine(outputDirectory, "Models"); _classesWithValidation = Directory.EnumerateFiles(modelsDir) .Select(x => new { Class = Path.GetFileNameWithoutExtension(x), Content = File.ReadAllText(x) }) .Where(x => x.Content.Contains("public virtual void Validate()")) .Select(x => x.Class) .ToHashSet(); Render.FileToFile("ModelExtensions.cs.template", definitions, Path.Combine(outputDirectory, "ModelExtensions.cs")); // generate version converter maps var allGeneratedModelClassNames = Directory .EnumerateFiles(Path.Combine(outputDirectory, "Models")) .Select(Path.GetFileNameWithoutExtension) .ToList(); var versionRegex = @"(^V|v)[0-9]+((alpha|beta)[0-9]+)?"; var typePairs = allGeneratedModelClassNames .OrderBy(x => x) .Select(x => new { Version = Regex.Match(x, versionRegex).Value?.ToLower(), Kinda = Regex.Replace(x, versionRegex, string.Empty), Type = x }) .Where(x => !string.IsNullOrEmpty(x.Version)) .GroupBy(x => x.Kinda) .Where(x => x.Count() > 1) .SelectMany(x => x.SelectMany((value, index) => x.Skip(index + 1), (first, second) => new { first, second })) .OrderBy(x => x.first.Kinda) .ThenBy(x => x.first.Version) .Select(x => (ITuple)Tuple.Create(x.first.Type, x.second.Type)) .ToList(); var versionFile = File.ReadAllText(Path.Combine(outputDirectory, "..", "Versioning", "VersionConverter.cs")); var manualMaps = Regex.Matches(versionFile, @"\.CreateMap<(?<T1>.+?),\s?(?<T2>.+?)>") .Select(x => Tuple.Create(x.Groups["T1"].Value, x.Groups["T2"].Value)) .ToList(); var versionConverterPairs = typePairs.Except(manualMaps).ToList(); Render.FileToFile("VersionConverter.cs.template", versionConverterPairs, Path.Combine(outputDirectory, "VersionConverter.cs")); Render.FileToFile("ModelOperators.cs.template", typePairs, Path.Combine(outputDirectory, "ModelOperators.cs")); }
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) { var serviceDiscovery = JimuClient.Host.Container.Resolve <IClientServiceDiscovery>(); var routes = serviceDiscovery.GetRoutesAsync().GetAwaiter().GetResult(); (from route in routes select route.ServiceDescriptor).OrderBy(x => x.RoutePath).ToList().ForEach(x => { var subsIndex = x.RoutePath.IndexOf('?'); subsIndex = subsIndex < 0 ? x.RoutePath.Length : subsIndex; var route = x.RoutePath.Substring(0, subsIndex); route = route.StartsWith('/') ? route : "/" + route; var paras = new List <IParameter>(); if (!string.IsNullOrEmpty(x.Parameters)) { var parameters = JimuHelper.Deserialize(TypeHelper.ReplaceTypeToJsType(x.Parameters), typeof(List <JimuServiceParameterDesc>)) as List <JimuServiceParameterDesc>; paras = GetParameters(parameters, x.HttpMethod); } if (x.GetMetadata <bool>("EnableAuthorization")) { paras.Add(new NonBodyParameter { Name = "Authorization", Type = "string", In = "header", Description = "Token", Required = true, Default = "Bearer " }); } var response = new Dictionary <string, Response>(); response.Add("200", GetResponse(x.ReturnDesc)); if (x.HttpMethod == "GET") { swaggerDoc.Paths.Add(route, new PathItem { Get = new Operation { Consumes = new List <string> { "application/json" }, OperationId = x.RoutePath, Parameters = paras, Produces = new List <string> { "application/json" }, Responses = response, Description = x.Comment } }); } else { swaggerDoc.Paths.Add(route, new PathItem { Post = new Operation { Consumes = new List <string> { "application/json" }, OperationId = x.RoutePath, Parameters = paras, Produces = new List <string> { "application/json" }, Responses = response, Description = x.Comment } }); } }); }
public async Task When_parameter_is_array_then_CSharp_is_correct() { //// Arrange var swagger = @"{ ""swagger"" : ""2.0"", ""info"" : { ""version"" : ""1.0.2"", ""title"" : ""Test API"" }, ""host"" : ""localhost:8080"", ""basePath"" : ""/"", ""tags"" : [ { ""name"" : ""api"" } ], ""schemes"" : [ ""http"" ], ""paths"" : { ""/removeElement"" : { ""delete"" : { ""tags"" : [ ""api"" ], ""summary"" : ""Removes elements"", ""description"" : ""Removes elements"", ""operationId"" : ""removeElement"", ""consumes"" : [ ""application/json"" ], ""produces"" : [ ""application/json"" ], ""parameters"" : [ { ""name"" : ""X-User"", ""in"" : ""header"", ""description"" : ""User identifier"", ""required"" : true, ""type"" : ""string"" }, { ""name"" : ""elementId"", ""in"" : ""query"", ""description"" : ""The ids of existing elements that should be removed"", ""required"" : false, ""type"" : ""array"", ""items"" : { ""type"" : ""integer"", ""format"" : ""int64"" }, } ], ""responses"" : { ""default"" : { ""description"" : ""successful operation"" } } } } }, ""definitions"" : { } } "; var document = await SwaggerDocument.FromJsonAsync(swagger); //// Act var settings = new SwaggerToCSharpClientGeneratorSettings { ClassName = "MyClass" }; var generator = new SwaggerToCSharpClientGenerator(document, settings); var code = generator.GenerateFile(); //// Assert Assert.IsTrue( code.Contains( @"foreach (var item_ in elementId) { urlBuilder_.Append(""elementId="").Append(System.Uri.EscapeDataString(System.Convert.ToString(item_, System.Globalization.CultureInfo.InvariantCulture))).Append(""&""); }")); }
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { swaggerDoc.paths.Add("/api/v1/usuario/token", new PathItem { post = new Operation { tags = new List <string> { "Usuario" }, consumes = new List <string> { "application/x-www-form-urlencoded" }, parameters = new List <Parameter> { new Parameter { type = "string", name = "grant_type", required = true, @in = "formData" }, new Parameter { type = "string", name = "username", required = true, @in = "formData" }, new Parameter { type = "string", name = "password", required = true, @in = "formData" } }, //responses = new Dictionary<string, Response>() //{ // { "200", new Response{ schema = schemaRegistry.GetOrRegister(typeof(string)) } } //} responses = new Dictionary <string, Response> { { "200", new Response { description = "Success", schema = new Schema { type = "object", properties = new Dictionary <string, Schema> { { "access_token", new Schema { type = "string" } }, { "token_type", new Schema { type = "string" } }, { "expires_in", new Schema { type = "integer" } } } } } } } } }); }