Exemple #1
0
        private static IOpenApiWriter BuildWriter(Stream stream, OpenApiTarget target)
        {
            StreamWriter writer = new StreamWriter(stream)
            {
                NewLine = "\n"
            };

            return(BuildWriter(writer, target));
        }
        private static string WriteEdmModelToOpenApi(IEdmModel model, OpenApiTarget target,
                                                     OpenApiWriterSettings settings = null)
        {
            MemoryStream stream = new MemoryStream();

            model.WriteOpenApi(stream, target, settings);
            stream.Flush();
            stream.Position = 0;
            return(new StreamReader(stream).ReadToEnd());
        }
Exemple #3
0
 private static IOpenApiWriter BuildWriter(TextWriter writer, OpenApiTarget target)
 {
     if (target == OpenApiTarget.Json)
     {
         return(new OpenApiJsonWriter(writer));
     }
     else
     {
         return(new OpenApiYamlWriter(writer));
     }
 }
Exemple #4
0
        private bool ProcessTarget(OpenApiTarget target)
        {
            if (Target != null)
            {
                Console.WriteLine("[Error:] Multiple [--json|-j|--yaml|-y] are not allowed.\n");
                PrintUsage();
                return(false);
            }

            Target = target;
            return(true);
        }
Exemple #5
0
        internal static string Write(this IOpenApiWritable element,
                                     OpenApiTarget target,
                                     Action <IOpenApiWriter, IOpenApiWritable> before = null,
                                     Action <IOpenApiWriter, IOpenApiWritable> after  = null)
        {
            Action <IOpenApiWriter> action = writer =>
            {
                before?.Invoke(writer, element);
                element?.Write(writer);
                after?.Invoke(writer, element);
                writer?.Flush();
            };

            return(Write(target, action));
        }
Exemple #6
0
        /// <summary>
        /// Outputs Edm model to an Open API artifact to the give text writer.
        /// </summary>
        /// <param name="model">Edm model to be written.</param>
        /// <param name="writer">The output text writer.</param>
        /// <param name="target">The Open API target.</param>
        /// <param name="settings">Settings for the generated Open API.</param>
        public static void WriteOpenApi(this IEdmModel model, TextWriter writer, OpenApiTarget target, OpenApiWriterSettings settings = null)
        {
            if (model == null)
            {
                throw Error.ArgumentNull(nameof(model));
            }

            if (writer == null)
            {
                throw Error.ArgumentNull(nameof(writer));
            }

            IOpenApiWriter openApiWriter = BuildWriter(writer, target);

            model.WriteOpenApi(openApiWriter, settings);
        }
Exemple #7
0
        internal static string Write(OpenApiTarget target, Action <IOpenApiWriter> action)
        {
            MemoryStream   stream = new MemoryStream();
            IOpenApiWriter writer;

            if (target == OpenApiTarget.Yaml)
            {
                writer = new OpenApiYamlWriter(new StreamWriter(stream));
            }
            else
            {
                writer = new OpenApiJsonWriter(new StreamWriter(stream));
            }

            action(writer);
            writer.Flush();
            stream.Position = 0;
            return(new StreamReader(stream).ReadToEnd());
        }
Exemple #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OpenApiGenerator"/> class.
 /// </summary>
 /// <param name="input">The input.</param>
 /// <param name="output">The output.</param>
 /// <param name="target">The output target.</param>
 public OpenApiGenerator(string output, OpenApiTarget target)
 {
     Output = output;
     Target = target;
 }
Exemple #9
0
        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 = OpenApiDocument.FromJsonAsync(temp);
                runner.Wait();
                var swaggerDocument = runner.Result;

                List <string> allops = new List <string>();
                Dictionary <string, OpenApiPathItem> itemsToRemove = new Dictionary <string, OpenApiPathItem>();
                // fix the operationIds.
                foreach (var operation in swaggerDocument.Operations)
                {
                    string suffix = "";
                    if (operation.Method == OpenApiOperationMethod.Post)
                    {
                        suffix = "Create";
                        // for creates we also want to add a header parameter to ensure we get the new object back.
                        OpenApiParameter swaggerParameter = new OpenApiParameter()
                        {
                            Type        = JsonObjectType.String,
                            Name        = "Prefer",
                            Default     = "return=representation",
                            Description = "Required in order for the service to return a JSON representation of the object.",
                            Kind        = OpenApiParameterKind.Header
                        };
                        operation.Operation.Parameters.Add(swaggerParameter);
                    }

                    if (operation.Method == OpenApiOperationMethod.Patch)
                    {
                        suffix = "Update";
                    }

                    if (operation.Method == OpenApiOperationMethod.Put)
                    {
                        suffix = "Put";
                    }


                    if (operation.Method == OpenApiOperationMethod.Delete)
                    {
                        suffix = "Delete";
                    }


                    if (operation.Method == OpenApiOperationMethod.Get)
                    {
                        if (operation.Path.Contains("{"))
                        {
                            suffix = "GetByKey";
                        }
                        else
                        {
                            suffix = "Get";
                        }
                    }

                    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("sharepointsites") || firstTagLower.Equals("savedqueries") || firstTagLower.Equals("sharepointdocumentlocations"))
                        {
                            ok2Delete = false;
                        }
                        if (firstTagLower.IndexOf("test") != -1 && !firstTagLower.Contains("QuickTest") && !firstTagLower.Contains("UpdateStateValue")
                            )
                        {
                            ok2Delete     = false;
                            firstTagLower = firstTagLower.Replace("test_", "");
                            firstTagLower = firstTagLower.Replace("test", "");
                            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("test", "");
                            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      = OpenApiParameterKind.Query;
                                parameter.Reference = null;
                                parameter.Schema    = null;
                                parameter.Type      = JsonObjectType.Integer;
                            }
                            if (name == "$skip")
                            {
                                parameter.Kind      = OpenApiParameterKind.Query;
                                parameter.Reference = null;
                                parameter.Schema    = null;
                                parameter.Type      = JsonObjectType.Integer;
                            }
                            if (name == "$search")
                            {
                                parameter.Kind      = OpenApiParameterKind.Query;
                                parameter.Reference = null;
                                parameter.Schema    = null;
                                parameter.Type      = JsonObjectType.String;
                            }
                            if (name == "$filter")
                            {
                                parameter.Kind      = OpenApiParameterKind.Query;
                                parameter.Reference = null;
                                parameter.Schema    = null;
                                parameter.Type      = JsonObjectType.String;
                            }
                            if (name == "$count")
                            {
                                parameter.Kind      = OpenApiParameterKind.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 != OpenApiParameterStyle.Undefined)
                        {
                            parameter.Style = OpenApiParameterStyle.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 == OpenApiParameterKind.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 JsonSchema();
                                    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);
                }

                /*
                 * foreach (var path in swaggerDocument.Paths)
                 * {
                 *  foreach (var parameter in path.Value.Parameters)
                 *  {
                 *      var name = parameter.Name;
                 *  }
                 * }
                 */
                /*
                 * Cleanup definitions.
                 */

                foreach (var definition in swaggerDocument.Definitions)
                {
                    foreach (var property in definition.Value.Properties)
                    {
                        // fix for doubles
                        if (property.Value != null && property.Value.Format != null && property.Value.Format.Equals("double"))
                        {
                            property.Value.Format = "decimal";
                        }
                        if (property.Key.Equals("adoxio_birthdate"))
                        {
                            property.Value.Format = "date";
                        }
                        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 CSharpClientGeneratorSettings
                {
                    ClassName = "DynamicsClient",
                    CSharpGeneratorSettings =
                    {
                        Namespace = "Dynamics"
                    }
                };

                var generator = new CSharpClientGenerator(swaggerDocument, generatorSettings);
                var code      = generator.GenerateFile();

                File.WriteAllText("DynamicsClient.cs", code);
            }

            //File.WriteAllText("dynamics-swagger.json", swagger);
        }
        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();

                        // || firstTagLower.Equals("equipments")

                        if (firstTagLower.Equals("incidents") || firstTagLower.Equals("sharepointdocumentlocations") || firstTagLower.Equals("sharepointsites") || firstTagLower.Equals("contacts") || firstTagLower.Equals("accounts") || firstTagLower.Equals("invoices") || firstTagLower.Equals("entitydefinitions") || firstTagLower.Equals("globaloptionsetdefinitions"))
                        {
                            ok2Delete = false;
                        }
                        if (firstTagLower.IndexOf("bcgov") != -1)
                        {
                            ok2Delete     = false;
                            firstTagLower = firstTagLower.Replace("bcgov_", "");
                            firstTagLower = firstTagLower.Replace("bcgov", "");
                            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("bcgov", "");
                            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
                    // changes to fix the “GetOkResponseModelModelModel…” generated models
                    // Based on Cannabis solution https://github.com/bcgov/jag-lcrb-carla-public/blob/master/cllc-interfaces/OData.OpenAPI/odata2openapi/Program.cs line 342

                    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 val.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;
                                }
                            }
                        }
                    } // end of adjustments to response
                }

                foreach (var opDelete in itemsToRemove)
                {
                    Debug.WriteLine($"Removing {opDelete.Key}");
                    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", "");

                // 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.

                /*
                 * var generatorSettings = new SwaggerToCSharpClientGeneratorSettings
                 * {
                 *  ClassName = "DynamicsClient",
                 *  CSharpGeneratorSettings =
                 *  {
                 *      Namespace = "<namespace>"
                 *  }
                 * };
                 *
                 * var generator = new SwaggerToCSharpClientGenerator(swaggerDocument, generatorSettings);
                 * var code = generator.GenerateFile();
                 *
                 * File.WriteAllText("<filename>", code);
                 */
            }

            // output the file.

            File.WriteAllText("dynamics-swagger.json", swagger);
        }
Exemple #11
0
        static void Main(string[] args)
        {
            bool getMetadata = false;

            // 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("C:\\tmp\\dynamics-metadata.xml", csdl);
            }
            else
            {
                csdl = File.ReadAllText("C:\\tmp\\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());

            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;

                // 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
                        };

                        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)
                    {
                        prefix = firstTag;
                        // Capitalize the first character.
                        if (prefix.Length > 0)
                        {
                            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)
                    {
                        // 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;
                        }

                        // many string parameters don't have the type defined.
                        if (parameter.Type == JsonObjectType.Null)
                        {
                            parameter.Type = JsonObjectType.String;
                        }

                        // we also need to align the schema if it exists.

                        if (parameter.Schema != null)
                        {
                            var schema = parameter.Schema;
                            if (schema.Type == JsonObjectType.Array)
                            {
                                // move schema up a level.
                                parameter.Items.Clear();
                                foreach (var schemaItem in schema.Items)
                                {
                                    parameter.Items.Add(schemaItem);
                                }
                                parameter.Schema = null;
                                parameter.Type   = JsonObjectType.Array;
                            }
                        }
                    }
                }

                swagger = swaggerDocument.ToJson(SchemaType.Swagger2);

                // fix up the swagger file.

                swagger = swagger.Replace("('{", "({");
                swagger = swagger.Replace("}')", "})");

                // 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("C:\\tmp\\dynamics-swagger.json", swagger);

            Console.Out.WriteLine(swagger);
        }
Exemple #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FileOpenApiGenerator"/> class.
 /// </summary>
 /// <param name="input">The input.</param>
 /// <param name="output">The output.</param>
 /// <param name="target">The output target.</param>
 public FileOpenApiGenerator(string input, string output, OpenApiTarget target)
     : base(output, target)
 {
     Input = input;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="UrlOpenApiGenerator"/> class.
 /// </summary>
 /// <param name="input">The input.</param>
 /// <param name="output">The output.</param>
 /// <param name="target">The output target.</param>
 public UrlOpenApiGenerator(Uri input, string output, OpenApiTarget target)
     : base(output, target)
 {
     Input = input;
 }