diff --git a/pom.xml b/pom.xml index 33f5f45881..6d4ff6b574 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ io.swagger.codegen.v3 swagger-codegen-generators - 1.0.51 + 1.0.52-SNAPSHOT jar @@ -256,28 +256,28 @@ org.mockito mockito-core - 5.11.0 + 5.12.0 test 8 - 3.0.61 + 3.0.62-SNAPSHOT 2.1.22 - 2.2.21 - 2.17.0 - 2.17.0 + 2.2.22 + 2.17.2 + 2.17.2 2.11.1 3.3.0 2.16.1 - 1.7.0 + 1.8.0 4.13.2 1.0.0 3.14.0 1.7.36 3.2.1 - 7.10.1 - 3.2.5 + 7.10.2 + 3.3.0 1.49 0.10.2 diff --git a/src/main/java/io/swagger/codegen/v3/generators/dotnet/AbstractCSharpCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/dotnet/AbstractCSharpCodegen.java index 8b846d9a36..4af6b28480 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/dotnet/AbstractCSharpCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/dotnet/AbstractCSharpCodegen.java @@ -11,6 +11,7 @@ import io.swagger.codegen.v3.generators.DefaultCodegenConfig; import io.swagger.codegen.v3.generators.handlebars.csharp.CsharpHelper; import io.swagger.codegen.v3.generators.handlebars.lambda.CamelCaseLambda; +import io.swagger.codegen.v3.generators.handlebars.lambda.CapitaliseLambda; import io.swagger.codegen.v3.generators.handlebars.lambda.IndentedLambda; import io.swagger.codegen.v3.generators.handlebars.lambda.LowercaseLambda; import io.swagger.codegen.v3.generators.handlebars.lambda.TitlecaseLambda; @@ -350,6 +351,7 @@ private void addHandlebarsLambdas(Map objs) { .put("titlecase", new TitlecaseLambda()) .put("camelcase", new CamelCaseLambda().generator(this)) .put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true)) + .put("capitalise", new CapitaliseLambda()) .put("indented", new IndentedLambda()) .put("indented_8", new IndentedLambda(8, " ")) .put("indented_12", new IndentedLambda(12, " ")) diff --git a/src/main/java/io/swagger/codegen/v3/generators/dotnet/CSharpClientCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/dotnet/CSharpClientCodegen.java index 9112e9cc3a..142ad9a280 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/dotnet/CSharpClientCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/dotnet/CSharpClientCodegen.java @@ -29,6 +29,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { @SuppressWarnings({"hiding"}) private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class); + private static final String NET471 = "v4.7.1"; private static final String NET45 = "v4.5"; private static final String NET40 = "v4.0"; private static final String NET35 = "v3.5"; @@ -48,10 +49,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { protected String modelDocPath = "docs/"; // Defines TargetFrameworkVersion in csproj files - protected String targetFramework = NET45; + protected String targetFramework = NET471; // Defines nuget identifiers for target framework - protected String targetFrameworkNuget = "net45"; + protected String targetFrameworkNuget = "net471"; protected boolean supportsAsync = Boolean.TRUE; protected boolean supportsUWP = Boolean.FALSE; protected boolean netStandard = Boolean.FALSE; @@ -106,6 +107,7 @@ public CSharpClientCodegen() { .put(NET35, ".NET Framework 3.5 compatible") .put(NET40, ".NET Framework 4.0 compatible") .put(NET45, ".NET Framework 4.5+ compatible") + .put(NET471, ".NET Framework 4.71+ compatible") .put(NETSTANDARD, ".NET Standard 1.3 compatible") .put(UWP, "Universal Windows Platform (IMPORTANT: this will be decommissioned and replaced by v5.0)") .build(); @@ -186,6 +188,16 @@ public CSharpClientCodegen() { @Override public void processOpts() { + + // process targetFramework first as it is used to get Template Dir + if (additionalProperties.containsKey(CodegenConstants.DOTNET_FRAMEWORK)) { + setTargetFramework((String) additionalProperties.get(CodegenConstants.DOTNET_FRAMEWORK)); + } else { + // Ensure default is set. + setTargetFramework(NET471); + additionalProperties.put(CodegenConstants.DOTNET_FRAMEWORK, this.targetFramework); + } + super.processOpts(); /* @@ -221,14 +233,6 @@ public void processOpts() { additionalProperties.put(CodegenConstants.VALIDATABLE, validatable); } - if (additionalProperties.containsKey(CodegenConstants.DOTNET_FRAMEWORK)) { - setTargetFramework((String) additionalProperties.get(CodegenConstants.DOTNET_FRAMEWORK)); - } else { - // Ensure default is set. - setTargetFramework(NET45); - additionalProperties.put(CodegenConstants.DOTNET_FRAMEWORK, this.targetFramework); - } - if (NET35.equals(this.targetFramework)) { // This is correct, mono will require you build .NET 3.5 sources using 4.0 SDK additionalProperties.put(MCS_NET_VERSION_KEY, "4"); @@ -273,10 +277,14 @@ public void processOpts() { setTargetFrameworkNuget("net40"); setSupportsAsync(Boolean.FALSE); - } else { + } else if (NET45.equals(this.targetFramework)) { additionalProperties.put(MCS_NET_VERSION_KEY, "4.5.2-api"); setTargetFrameworkNuget("net45"); setSupportsAsync(Boolean.TRUE); + } else { + additionalProperties.put(MCS_NET_VERSION_KEY, "4.7.1-api"); + setTargetFrameworkNuget("net471"); + setSupportsAsync(Boolean.TRUE); } if (additionalProperties.containsKey(CodegenConstants.GENERATE_PROPERTY_CHANGED)) { @@ -375,15 +383,17 @@ public void processOpts() { clientPackageDir, "ReadOnlyDictionary.cs")); } - if (Boolean.FALSE.equals(this.netStandard) && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { + if (Boolean.FALSE.equals(this.netStandard) && Boolean.FALSE.equals(this.netCoreProjectFileFlag) && !NET471.equals(this.targetFramework)) { supportingFiles.add(new SupportingFile("compile.mustache", "", "build.bat")); supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "build.sh")); - // copy package.config to nuget's standard location for project-level installs - supportingFiles.add(new SupportingFile("packages.config.mustache", packageFolder + File.separator, "packages.config")); + if (!NET471.equals(this.targetFramework)) { + // copy package.config to nuget's standard location for project-level installs + supportingFiles.add(new SupportingFile("packages.config.mustache", packageFolder + File.separator, "packages.config")); + } // .travis.yml for travis-ci.org CI supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml")); - } else if (Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { + } else if (Boolean.FALSE.equals(this.netCoreProjectFileFlag) && !NET471.equals(this.targetFramework)) { supportingFiles.add(new SupportingFile("project.json.mustache", packageFolder + File.separator, "project.json")); } @@ -420,7 +430,7 @@ public void processOpts() { supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); - if (optionalAssemblyInfoFlag && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { + if (optionalAssemblyInfoFlag && Boolean.FALSE.equals(this.netCoreProjectFileFlag) && !NET471.equals(this.targetFramework)) { supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", packageFolder + File.separator + "Properties", "AssemblyInfo.cs")); } if (optionalProjectFileFlag) { @@ -501,6 +511,13 @@ public String getName() { return "csharp"; } + public String getDefaultTemplateDir() { + if (NET471.equals(this.targetFramework)) { + return "csharp-471"; + } + return "csharp"; + } + @Override public String getHelp() { return "Generates a CSharp client library."; diff --git a/src/main/resources/handlebars/csharp-471/ApiClient.mustache b/src/main/resources/handlebars/csharp-471/ApiClient.mustache new file mode 100644 index 0000000000..a70bc9d656 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/ApiClient.mustache @@ -0,0 +1,602 @@ +{{>partial_header}} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; +using System.IO; +{{^netStandard}} +{{^supportsUWP}} +using System.Web; +{{/supportsUWP}} +{{/netStandard}} +using System.Linq; +using System.Net.Http; +using System.Text; +using Newtonsoft.Json; +{{#netStandard}} +using RestSharp.Portable; +using RestSharp.Portable.HttpClient; +{{/netStandard}} +{{^netStandard}} +using RestSharp; +{{/netStandard}} + +namespace {{packageName}}.Client +{ + /// + /// API client is mainly responsible for making the HTTP call to the API backend. + /// + {{>visibility}} partial class ApiClient + { + private JsonSerializerSettings serializerSettings = new JsonSerializerSettings + { + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor + }; + + /// + /// Allows for extending request processing for generated code. + /// + /// The RestSharp request object + partial void InterceptRequest(RestRequest request); + + /// + /// Allows for extending response processing for generated code. + /// + /// The RestSharp request object + /// The RestSharp response object + partial void InterceptResponse(RestRequest request, RestResponse response); + + /// + /// Initializes a new instance of the class + /// with default configuration. + /// + public ApiClient() + { + Configuration = {{packageName}}.Client.Configuration.Default; + RestClient = new RestClient("{{{basePath}}}"); + {{#netStandard}} + RestClient.IgnoreResponseStatusCode = true; + {{/netStandard}} + } + + /// + /// Initializes a new instance of the class + /// with default base path ({{{basePath}}}). + /// + /// An instance of Configuration. + public ApiClient(Configuration config) + { + Configuration = config ?? {{packageName}}.Client.Configuration.Default; + + RestClient = new RestClient(Configuration.BasePath); + {{#netStandard}} + RestClient.IgnoreResponseStatusCode = true; + {{/netStandard}} + } + + /// + /// Initializes a new instance of the class + /// with default configuration. + /// + /// The base path. + public ApiClient(String basePath = "{{{basePath}}}") + { + if (String.IsNullOrEmpty(basePath)) + throw new ArgumentException("basePath cannot be empty"); + + RestClient = new RestClient(basePath); + {{#netStandard}} + RestClient.IgnoreResponseStatusCode = true; + {{/netStandard}} + Configuration = Client.Configuration.Default; + } + + /// + /// Gets or sets the default API client for making HTTP calls. + /// + /// The default API client. + [Obsolete("ApiClient.Default is deprecated, please use 'Configuration.Default.ApiClient' instead.")] + public static ApiClient Default; + + /// + /// Gets or sets an instance of the IReadableConfiguration. + /// + /// An instance of the IReadableConfiguration. + /// + /// helps us to avoid modifying possibly global + /// configuration values from within a given client. It does not guarantee thread-safety + /// of the instance in any way. + /// + public IReadableConfiguration Configuration { get; set; } + + /// + /// Gets or sets the RestClient. + /// + /// An instance of the RestClient + public RestClient RestClient { get; set; } + + // Creates and sets up a RestRequest prior to a call. + private RestRequest PrepareRequest( + String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody, + Dictionary headerParams, Dictionary formParams, + Dictionary fileParams, Dictionary pathParams, + String contentType) + { + var request = new RestRequest(path, method); + {{#netStandard}} + // disable ResetSharp.Portable built-in serialization + request.Serializer = null; + {{/netStandard}} + + // add path parameter, if any + foreach(var param in pathParams) + request.AddParameter(param.Key, param.Value, ParameterType.UrlSegment); + + // add header parameter, if any + foreach(var param in headerParams) + request.AddHeader(param.Key, param.Value); + + // add query parameter, if any + foreach(var param in queryParams) + request.AddQueryParameter(param.Key, param.Value); + + // add form parameter, if any + foreach(var param in formParams) + request.AddParameter(param.Key, param.Value); + + // add file parameter, if any + foreach(var param in fileParams) + { + {{#netStandard}} + request.AddFile(param.Value); + {{/netStandard}} + {{^netStandard}} + {{^supportsUWP}} + request.AddFile(param.Value.Name, param.Value.FileName, param.Value.ContentType); + {{/supportsUWP}} + {{#supportsUWP}} + byte[] paramWriter = null; + param.Value.Writer = delegate (Stream stream) { paramWriter = ToByteArray(stream); }; + request.AddFile(param.Value.Name, paramWriter, param.Value.FileName, param.Value.ContentType); + {{/supportsUWP}} + {{/netStandard}} + } + + if (postBody != null) // http body (model or byte[]) parameter + { + {{#netStandard}} + request.AddParameter(new Parameter { Value = postBody, Type = ParameterType.RequestBody, ContentType = contentType }); + {{/netStandard}} + {{^netStandard}} + request.AddParameter(contentType, postBody, ParameterType.RequestBody); + {{/netStandard}} + } + + return request; + } + + /// + /// Makes the HTTP request (Sync). + /// + /// URL path. + /// HTTP method. + /// Query parameters. + /// HTTP body (POST request). + /// Header parameters. + /// Form parameters. + /// File parameters. + /// Path parameters. + /// Content Type of the request + /// Object + public Object CallApi( + String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody, + Dictionary headerParams, Dictionary formParams, + Dictionary fileParams, Dictionary pathParams, + String contentType) + { + var request = PrepareRequest( + path, method, queryParams, postBody, headerParams, formParams, fileParams, + pathParams, contentType); + + var options = new RestClientOptions + { + Timeout = TimeSpan.FromMilliseconds(Configuration.Timeout), // Set the timeout + UserAgent = Configuration.UserAgent, // Set the user agent + BaseUrl = new Uri(Configuration.BasePath) + }; + // Use the options to create a new RestClient + RestClient = new RestClient(options); + InterceptRequest(request); + {{#netStandard}} + var response = RestClient.Execute(request).Result; + {{/netStandard}} + {{^netStandard}} + {{^supportsUWP}} + var response = RestClient.Execute(request); + {{/supportsUWP}} + {{#supportsUWP}} + // Using async method to perform sync call (uwp-only) + var response = RestClient.ExecuteAsync(request).Result; + {{/supportsUWP}} + {{/netStandard}} + InterceptResponse(request, response); + + return (Object) response; + } + {{#supportsAsync}} + /// + /// Makes the asynchronous HTTP request. + /// + /// URL path. + /// HTTP method. + /// Query parameters. + /// HTTP body (POST request). + /// Header parameters. + /// Form parameters. + /// File parameters. + /// Path parameters. + /// Content type. + /// The Task instance. + public async System.Threading.Tasks.Task CallApiAsync( + String path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody, + Dictionary headerParams, Dictionary formParams, + Dictionary fileParams, Dictionary pathParams, + String contentType) + { + var request = PrepareRequest( + path, method, queryParams, postBody, headerParams, formParams, fileParams, + pathParams, contentType); + InterceptRequest(request); + var response = await RestClient.Execute{{^netStandard}}Async{{/netStandard}}(request); + InterceptResponse(request, response); + return (Object)response; + }{{/supportsAsync}} + + /// + /// Escape string (url-encoded). + /// + /// String to be escaped. + /// Escaped string. + public string EscapeString(string str) + { + return UrlEncode(str); + } + + /// + /// Create FileParameter based on Stream. + /// + /// Parameter name. + /// Input stream. + /// FileParameter. + public FileParameter ParameterToFile(string name, Stream stream) + { + if (stream is FileStream) + return FileParameter.Create(name, ReadAsBytes(stream), Path.GetFileName(((FileStream)stream).Name)); + else + return FileParameter.Create(name, ReadAsBytes(stream), "no_file_name_provided"); + } + + public FileParameter ParameterToFile(string name, byte[] stream) + { + return FileParameter.Create(name, stream, "no_file_name_provided"); + } + + /// + /// If parameter is DateTime, output in a formatted string (default ISO 8601), customizable with Configuration.DateTime. + /// If parameter is a list, join the list with ",". + /// Otherwise just return the string. + /// + /// The parameter (header, path, query, form). + /// Formatted string. + public string ParameterToString(object obj) + { + if (obj is DateTime) + // Return a formatted date string - Can be customized with Configuration.DateTimeFormat + // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o") + // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 + // For example: 2009-06-15T13:45:30.0000000 + return ((DateTime)obj).ToString (Configuration.DateTimeFormat); + else if (obj is DateTimeOffset) + // Return a formatted date string - Can be customized with Configuration.DateTimeFormat + // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o") + // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 + // For example: 2009-06-15T13:45:30.0000000 + return ((DateTimeOffset)obj).ToString (Configuration.DateTimeFormat); + else if (obj is IList) + { + var flattenedString = new StringBuilder(); + foreach (var param in (IList)obj) + { + if (flattenedString.Length > 0) + flattenedString.Append(","); + flattenedString.Append(param); + } + return flattenedString.ToString(); + } + else + return Convert.ToString (obj); + } + + /// + /// Deserialize the JSON string into a proper object. + /// + /// The HTTP response. + /// Object type. + /// Object representation of the JSON string. + public object Deserialize(RestResponse response, Type type) + { + {{^netStandard}}IList{{/netStandard}}{{#netStandard}}IHttpHeaders{{/netStandard}} headers = response.Headers.Cast().ToList();; + if (type == typeof(byte[])) // return byte array + { + return response.RawBytes; + } + + // TODO: ? if (type.IsAssignableFrom(typeof(Stream))) + if (type == typeof(Stream)) + { + if (headers != null) + { + var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath) + ? Path.GetTempPath() + : Configuration.TempFolderPath; + var regex = new Regex(@"Content-Disposition=.*filename=['""]?([^'""\s]+)['""]?$"); + foreach (var header in headers) + { + var match = regex.Match(header.ToString()); + if (match.Success) + { + string fileName = filePath + SanitizeFilename(match.Groups[1].Value.Replace("\"", "").Replace("'", "")); + File.WriteAllBytes(fileName, response.RawBytes); + return new FileStream(fileName, FileMode.Open); + } + } + } + var stream = new MemoryStream(response.RawBytes); + return stream; + } + + if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object + { + return DateTime.Parse(response.Content, null, System.Globalization.DateTimeStyles.RoundtripKind); + } + + if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type + { + return ConvertType(response.Content, type); + } + + // at this point, it must be a model (json) + try + { + return JsonConvert.DeserializeObject(response.Content, type, serializerSettings); + } + catch (Exception e) + { + throw new ApiException(500, e.Message); + } + } + + /// + /// Serialize an input (model) into JSON string + /// + /// Object. + /// JSON string. + public String Serialize(object obj) + { + try + { + return obj != null ? JsonConvert.SerializeObject(obj) : null; + } + catch (Exception e) + { + throw new ApiException(500, e.Message); + } + } + + /// + ///Check if the given MIME is a JSON MIME. + ///JSON MIME examples: + /// application/json + /// application/json; charset=UTF8 + /// APPLICATION/JSON + /// application/vnd.company+json + /// + /// MIME + /// Returns True if MIME type is json. + public bool IsJsonMime(String mime) + { + var jsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"); + return mime != null && (jsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json")); + } + + /// + /// Select the Content-Type header's value from the given content-type array: + /// if JSON type exists in the given array, use it; + /// otherwise use the first one defined in 'consumes' + /// + /// The Content-Type array to select from. + /// The Content-Type header to use. + public String SelectHeaderContentType(String[] contentTypes) + { + if (contentTypes.Length == 0) + return "application/json"; + + foreach (var contentType in contentTypes) + { + if (IsJsonMime(contentType.ToLower())) + return contentType; + } + + return contentTypes[0]; // use the first content type specified in 'consumes' + } + + /// + /// Select the Accept header's value from the given accepts array: + /// if JSON exists in the given array, use it; + /// otherwise use all of them (joining into a string) + /// + /// The accepts array to select from. + /// The Accept header to use. + public String SelectHeaderAccept(String[] accepts) + { + if (accepts.Length == 0) + return null; + + if (accepts.Contains("application/json", StringComparer.OrdinalIgnoreCase)) + return "application/json"; + + return String.Join(",", accepts); + } + + /// + /// Encode string in base64 format. + /// + /// String to be encoded. + /// Encoded string. + public static string Base64Encode(string text) + { + return System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text)); + } + + /// + /// Dynamically cast the object into target type. + /// + /// Object to be casted + /// Target type + /// Casted object + {{#supportsAsync}} + public static dynamic ConvertType(dynamic fromObject, Type toObject) + {{/supportsAsync}} + {{^supportsAsync}} + public static object ConvertType(T fromObject, Type toObject) where T : class + {{/supportsAsync}} + { + return Convert.ChangeType(fromObject, toObject); + } + + /// + /// Convert stream to byte array + /// + /// Input stream to be converted + /// Byte array + public static byte[] ReadAsBytes(Stream inputStream) + { + byte[] buf = new byte[16*1024]; + using (MemoryStream ms = new MemoryStream()) + { + int count; + while ((count = inputStream.Read(buf, 0, buf.Length)) > 0) + { + ms.Write(buf, 0, count); + } + return ms.ToArray(); + } + } + + /// + /// URL encode a string + /// Credit/Ref: https://github.com/restsharp/RestSharp/blob/master/RestSharp/Extensions/StringExtensions.cs#L50 + /// + /// String to be URL encoded + /// Byte array + public static string UrlEncode(string input) + { + const int maxLength = 32766; + + if (input == null) + { + throw new ArgumentNullException("input"); + } + + if (input.Length <= maxLength) + { + return Uri.EscapeDataString(input); + } + + StringBuilder sb = new StringBuilder(input.Length * 2); + int index = 0; + + while (index < input.Length) + { + int length = Math.Min(input.Length - index, maxLength); + string subString = input.Substring(index, length); + + sb.Append(Uri.EscapeDataString(subString)); + index += subString.Length; + } + + return sb.ToString(); + } + + /// + /// Sanitize filename by removing the path + /// + /// Filename + /// Filename + public static string SanitizeFilename(string filename) + { + Match match = Regex.Match(filename, @".*[/\\](.*)$"); + + if (match.Success) + { + return match.Groups[1].Value; + } + else + { + return filename; + } + } + {{^netStandard}} + {{#supportsUWP}} + /// + /// Convert stream to byte array + /// + /// IO stream + /// Byte array + public static byte[] ToByteArray(Stream stream) + { + stream.Position = 0; + byte[] buffer = new byte[stream.Length]; + for (int totalBytesCopied = 0; totalBytesCopied < stream.Length;) + totalBytesCopied += stream.Read(buffer, totalBytesCopied, Convert.ToInt32(stream.Length) - totalBytesCopied); + return buffer; + } + {{/supportsUWP}} + {{/netStandard}} + + /// + /// Convert params to key/value pairs. + /// Use collectionFormat to properly format lists and collections. + /// + /// Key name. + /// Value object. + /// A list of KeyValuePairs + public IEnumerable> ParameterToKeyValuePairs(string collectionFormat, string name, object value) + { + var parameters = new List>(); + + if (IsCollection(value) && collectionFormat == "multi") + { + var valueCollection = value as IEnumerable; + parameters.AddRange(from object item in valueCollection select new KeyValuePair(name, ParameterToString(item))); + } + else + { + parameters.Add(new KeyValuePair(name, ParameterToString(value))); + } + + return parameters; + } + + /// + /// Check if generic object is a collection. + /// + /// + /// True if object is a collection type + private static bool IsCollection(object value) + { + return value is IList || value is ICollection; + } + } +} diff --git a/src/main/resources/handlebars/csharp-471/ApiException.mustache b/src/main/resources/handlebars/csharp-471/ApiException.mustache new file mode 100644 index 0000000000..ca8044580f --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/ApiException.mustache @@ -0,0 +1,51 @@ +{{>partial_header}} +using System; + +namespace {{packageName}}.Client +{ + /// + /// API Exception + /// + {{>visibility}} class ApiException : Exception + { + /// + /// Gets or sets the error code (HTTP status code) + /// + /// The error code (HTTP status code). + public int ErrorCode { get; set; } + + /// + /// Gets or sets the error content (body json object) + /// + /// The error content (Http response body). + public {{#supportsAsync}}dynamic{{/supportsAsync}}{{^supportsAsync}}object{{/supportsAsync}} ErrorContent { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + public ApiException() {} + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + public ApiException(int errorCode, string message) : base(message) + { + this.ErrorCode = errorCode; + } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + public ApiException(int errorCode, string message, {{#supportsAsync}}dynamic{{/supportsAsync}}{{^supportsAsync}}object{{/supportsAsync}} errorContent = null) : base(message) + { + this.ErrorCode = errorCode; + this.ErrorContent = errorContent; + } + } + +} diff --git a/src/main/resources/handlebars/csharp-471/ApiResponse.mustache b/src/main/resources/handlebars/csharp-471/ApiResponse.mustache new file mode 100644 index 0000000000..d04575d7ad --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/ApiResponse.mustache @@ -0,0 +1,45 @@ +{{>partial_header}} +using System; +using System.Collections.Generic; + +namespace {{packageName}}.Client +{ + /// + /// API Response + /// + {{>visibility}} class ApiResponse + { + /// + /// Gets or sets the status code (HTTP status code) + /// + /// The status code. + public int StatusCode { get; private set; } + + /// + /// Gets or sets the HTTP headers + /// + /// HTTP headers + public IDictionary Headers { get; private set; } + + /// + /// Gets or sets the data (parsed HTTP body) + /// + /// The data. + public T Data { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// HTTP headers. + /// Data (parsed HTTP body) + public ApiResponse(int statusCode, IDictionary headers, T data) + { + this.StatusCode= statusCode; + this.Headers = headers; + this.Data = data; + } + + } + +} diff --git a/src/main/resources/handlebars/csharp-471/AssemblyInfo.mustache b/src/main/resources/handlebars/csharp-471/AssemblyInfo.mustache new file mode 100644 index 0000000000..bf80d7d456 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/AssemblyInfo.mustache @@ -0,0 +1,32 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("{{packageTitle}}")] +[assembly: AssemblyDescription("{{packageDescription}}")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("{{packageCompany}}")] +[assembly: AssemblyProduct("{{packageProductName}}")] +[assembly: AssemblyCopyright("{{packageCopyright}}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("{{packageVersion}}")] +[assembly: AssemblyFileVersion("{{packageVersion}}")] diff --git a/src/main/resources/handlebars/csharp-471/Configuration.mustache b/src/main/resources/handlebars/csharp-471/Configuration.mustache new file mode 100644 index 0000000000..c760f995b9 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/Configuration.mustache @@ -0,0 +1,493 @@ +{{>partial_header}} +using System; +using System.Reflection; +{{^net35}} +using System.Collections.Concurrent; +{{/net35}} +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using RestSharp; + +namespace {{packageName}}.Client +{ + /// + /// Represents a set of configuration settings + /// + {{>visibility}} class Configuration : IReadableConfiguration + { + #region Constants + + /// + /// Version of the package. + /// + /// Version of the package. + public const string Version = "{{packageVersion}}"; + + /// + /// Identifier for ISO 8601 DateTime Format + /// + /// See https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 for more information. + // ReSharper disable once InconsistentNaming + public const string ISO8601_DATETIME_FORMAT = "o"; + + #endregion Constants + + #region Static Members + + private static readonly object GlobalConfigSync = new { }; + private static Configuration _globalConfiguration; + + /// + /// Default creation of exceptions for a given method name and response object + /// + public static readonly ExceptionFactory DefaultExceptionFactory = (methodName, response) => + { + var status = (int)response.StatusCode; + if (status >= 400) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.Content), + response.Content); + } + {{^netStandard}}if (status == 0) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.ErrorMessage), response.ErrorMessage); + }{{/netStandard}} + return null; + }; + + /// + /// Gets or sets the default Configuration. + /// + /// Configuration. + public static Configuration Default + { + get { return _globalConfiguration; } + set + { + lock (GlobalConfigSync) + { + _globalConfiguration = value; + } + } + } + + #endregion Static Members + + #region Private Members + + /// + /// Gets or sets the API key based on the authentication name. + /// + /// The API key. + private IDictionary _apiKey = null; + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// The prefix of the API key. + private IDictionary _apiKeyPrefix = null; + + private string _dateTimeFormat = ISO8601_DATETIME_FORMAT; + private string _tempFolderPath = Path.GetTempPath(); + + #endregion Private Members + + #region Constructors + + static Configuration() + { + _globalConfiguration = new GlobalConfiguration(); + } + + /// + /// Initializes a new instance of the class + /// + public Configuration() + { + UserAgent = "{{#httpUserAgent}}{{.}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{packageVersion}}/csharp{{/httpUserAgent}}"; + BasePath = "{{{basePath}}}"; + DefaultHeader = new {{^net35}}Concurrent{{/net35}}Dictionary(); + ApiKey = new {{^net35}}Concurrent{{/net35}}Dictionary(); + ApiKeyPrefix = new {{^net35}}Concurrent{{/net35}}Dictionary(); + + Timeout = 100000; + } + + /// + /// Initializes a new instance of the class + /// + public Configuration( + IDictionary defaultHeader, + IDictionary apiKey, + IDictionary apiKeyPrefix, + string basePath = "{{{basePath}}}") : this() + { + if (string.{{^net35}}IsNullOrWhiteSpace{{/net35}}{{#net35}}IsNullOrEmpty{{/net35}}(basePath)) + throw new ArgumentException("The provided basePath is invalid.", "basePath"); + if (defaultHeader == null) + throw new ArgumentNullException("defaultHeader"); + if (apiKey == null) + throw new ArgumentNullException("apiKey"); + if (apiKeyPrefix == null) + throw new ArgumentNullException("apiKeyPrefix"); + + BasePath = basePath; + + foreach (var keyValuePair in defaultHeader) + { + DefaultHeader.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKey) + { + ApiKey.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKeyPrefix) + { + ApiKeyPrefix.Add(keyValuePair); + } + } + + /// + /// Initializes a new instance of the class with different settings + /// + /// Api client + /// Dictionary of default HTTP header + /// Username + /// Password + /// accessToken + /// Dictionary of API key + /// Dictionary of API key prefix + /// Temp folder path + /// DateTime format string + /// HTTP connection timeout (in milliseconds) + /// HTTP user agent + [Obsolete("Use explicit object construction and setting of properties.", true)] + public Configuration( + // ReSharper disable UnusedParameter.Local + ApiClient apiClient = null, + IDictionary defaultHeader = null, + string username = null, + string password = null, + string accessToken = null, + IDictionary apiKey = null, + IDictionary apiKeyPrefix = null, + string tempFolderPath = null, + string dateTimeFormat = null, + int timeout = 100000, + string userAgent = "{{#httpUserAgent}}{{.}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{packageVersion}}/csharp{{/httpUserAgent}}" + // ReSharper restore UnusedParameter.Local + ) + { + + } + + /// + /// Initializes a new instance of the Configuration class. + /// + /// Api client. + [Obsolete("This constructor caused unexpected sharing of static data. It is no longer supported.", true)] + // ReSharper disable once UnusedParameter.Local + public Configuration(ApiClient apiClient) + { + + } + + #endregion Constructors + + + #region Properties + + private ApiClient _apiClient = null; + /// + /// Gets an instance of an ApiClient for this configuration + /// + public virtual ApiClient ApiClient + { + get + { + if (_apiClient == null) _apiClient = CreateApiClient(); + return _apiClient; + } + } + + private String _basePath = null; + /// + /// Gets or sets the base path for API access. + /// + public virtual string BasePath { + get { return _basePath; } + set { + _basePath = value; + // pass-through to ApiClient if it's set. + if (_apiClient != null) { + _apiClient.RestClient = new RestClient(new RestClientOptions { + BaseUrl = new Uri(_basePath) + }); + + } + } + } + + /// + /// Gets or sets the default header. + /// + public virtual IDictionary DefaultHeader { get; set; } + + private int _timeout = 100000; + /// + /// Gets or sets the HTTP timeout (milliseconds) of ApiClient. Default to 100000 milliseconds. + /// + public virtual int Timeout + { + {{#netStandard}}get + { + if (_apiClient == null) + { + return _timeout; + } else + { + return (int)ApiClient.RestClient.Timeout.GetValueOrDefault(TimeSpan.FromSeconds(100)).TotalMilliseconds; + } + } + set + { + _timeout = value; + if (_apiClient != null) + { + ApiClient.RestClient.Timeout = TimeSpan.FromMilliseconds(_timeout); + } + }{{/netStandard}}{{^netStandard}} + get + { + if (_apiClient == null) + { + return _timeout; + } + else + { + return (int)ApiClient.RestClient.Options.Timeout.GetValueOrDefault(TimeSpan.FromSeconds(100)).TotalMilliseconds; + } + } + set + { + _timeout = value; + if (_apiClient != null) + { + ApiClient.RestClient = new RestClient(new RestClientOptions{ + Timeout = TimeSpan.FromMilliseconds(_timeout) + }); + }; + }{{/netStandard}} + } + + /// + /// Gets or sets the HTTP user agent. + /// + /// Http user agent. + public virtual string UserAgent { get; set; } + + /// + /// Gets or sets the username (HTTP basic authentication). + /// + /// The username. + public virtual string Username { get; set; } + + /// + /// Gets or sets the password (HTTP basic authentication). + /// + /// The password. + public virtual string Password { get; set; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + public string GetApiKeyWithPrefix(string apiKeyIdentifier) + { + var apiKeyValue = ""; + ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue); + var apiKeyPrefix = ""; + if (ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix)) + return apiKeyPrefix + " " + apiKeyValue; + else + return apiKeyValue; + } + + /// + /// Gets or sets the access token for OAuth2 authentication. + /// + /// The access token. + public virtual string AccessToken { get; set; } + + /// + /// Gets or sets the temporary folder path to store the files downloaded from the server. + /// + /// Folder path. + public virtual string TempFolderPath + { + get { return _tempFolderPath; } + + set + { + if (string.IsNullOrEmpty(value)) + { + // Possible breaking change since swagger-codegen 2.2.1, enforce a valid temporary path on set. + _tempFolderPath = Path.GetTempPath(); + return; + } + + // create the directory if it does not exist + if (!Directory.Exists(value)) + { + Directory.CreateDirectory(value); + } + + // check if the path contains directory separator at the end + if (value[value.Length - 1] == Path.DirectorySeparatorChar) + { + _tempFolderPath = value; + } + else + { + _tempFolderPath = value + Path.DirectorySeparatorChar; + } + } + } + + /// + /// Gets or sets the the date time format used when serializing in the ApiClient + /// By default, it's set to ISO 8601 - "o", for others see: + /// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx + /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx + /// No validation is done to ensure that the string you're providing is valid + /// + /// The DateTimeFormat string + public virtual string DateTimeFormat + { + get { return _dateTimeFormat; } + set + { + if (string.IsNullOrEmpty(value)) + { + // Never allow a blank or null string, go back to the default + _dateTimeFormat = ISO8601_DATETIME_FORMAT; + return; + } + + // Caution, no validation when you choose date time format other than ISO 8601 + // Take a look at the above links + _dateTimeFormat = value; + } + } + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// The prefix of the API key. + public virtual IDictionary ApiKeyPrefix + { + get { return _apiKeyPrefix; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKeyPrefix collection may not be null."); + } + _apiKeyPrefix = value; + } + } + + /// + /// Gets or sets the API key based on the authentication name. + /// + /// The API key. + public virtual IDictionary ApiKey + { + get { return _apiKey; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKey collection may not be null."); + } + _apiKey = value; + } + } + + #endregion Properties + + #region Methods + + /// + /// Add default header. + /// + /// Header field name. + /// Header field value. + /// + public void AddDefaultHeader(string key, string value) + { + DefaultHeader[key] = value; + } + + /// + /// Creates a new based on this instance. + /// + /// + public ApiClient CreateApiClient() + { + return new ApiClient(this); + } + + + /// + /// Returns a string with essential information for debugging. + /// + public static String ToDebugReport() + { + String report = "C# SDK ({{{packageName}}}) Debug Report:\n"; + {{^netStandard}} + {{^supportsUWP}} + report += " OS: " + System.Environment.OSVersion + "\n"; + report += " .NET Framework Version: " + System.Environment.Version + "\n"; + {{/supportsUWP}} + {{/netStandard}} + {{#netStandard}} + report += " OS: " + System.Runtime.InteropServices.RuntimeInformation.OSDescription + "\n"; + {{/netStandard}} + report += " Version of the API: {{{version}}}\n"; + report += " SDK Package Version: {{{packageVersion}}}\n"; + + return report; + } + + /// + /// Add Api Key Header. + /// + /// Api Key name. + /// Api Key value. + /// + public void AddApiKey(string key, string value) + { + ApiKey[key] = value; + } + + /// + /// Sets the API key prefix. + /// + /// Api Key name. + /// Api Key value. + public void AddApiKeyPrefix(string key, string value) + { + ApiKeyPrefix[key] = value; + } + + #endregion Methods + } +} diff --git a/src/main/resources/handlebars/csharp-471/ExceptionFactory.mustache b/src/main/resources/handlebars/csharp-471/ExceptionFactory.mustache new file mode 100644 index 0000000000..5ce23ca6ac --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/ExceptionFactory.mustache @@ -0,0 +1,20 @@ +{{>partial_header}} + +using System; +{{#netStandard}} +using RestSharp.Portable; +{{/netStandard}} +{{^netStandard}} +using RestSharp; +{{/netStandard}} + +namespace {{packageName}}.Client +{ + /// + /// A delegate to ExceptionFactory method + /// + /// Method name + /// Response + /// Exceptions + {{>visibility}} delegate Exception ExceptionFactory(string methodName, RestResponse response); +} diff --git a/src/main/resources/handlebars/csharp-471/FodyWeavers.xml b/src/main/resources/handlebars/csharp-471/FodyWeavers.xml new file mode 100644 index 0000000000..da017fcbf6 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/FodyWeavers.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/handlebars/csharp-471/GlobalConfiguration.mustache b/src/main/resources/handlebars/csharp-471/GlobalConfiguration.mustache new file mode 100644 index 0000000000..b218d5cc34 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/GlobalConfiguration.mustache @@ -0,0 +1,25 @@ +{{>partial_header}} + +using System; +using System.Reflection; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; + +namespace {{packageName}}.Client +{ + /// + /// provides a compile-time extension point for globally configuring + /// API Clients. + /// + /// + /// A customized implementation via partial class may reside in another file and may + /// be excluded from automatic generation via a .swagger-codegen-ignore file. + /// + public partial class GlobalConfiguration : Configuration + { + + } +} \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/IApiAccessor.mustache b/src/main/resources/handlebars/csharp-471/IApiAccessor.mustache new file mode 100644 index 0000000000..a3355a1226 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/IApiAccessor.mustache @@ -0,0 +1,38 @@ +{{>partial_header}} + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +{{#netStandard}} +using RestSharp.Portable; +{{/netStandard}} +{{^netStandard}} +using RestSharp; +{{/netStandard}} + +namespace {{packageName}}.Client +{ + /// + /// Represents configuration aspects required to interact with the API endpoints. + /// + {{>visibility}} interface IApiAccessor + { + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + Configuration Configuration {get; set;} + + /// + /// Gets the base path of the API client. + /// + /// The base path + String GetBasePath(); + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + ExceptionFactory ExceptionFactory { get; set; } + } +} diff --git a/src/main/resources/handlebars/csharp-471/IReadableConfiguration.mustache b/src/main/resources/handlebars/csharp-471/IReadableConfiguration.mustache new file mode 100644 index 0000000000..ce165e0c81 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/IReadableConfiguration.mustache @@ -0,0 +1,85 @@ +{{>partial_header}} + +using System.Collections.Generic; + +namespace {{packageName}}.Client +{ + /// + /// Represents a readable-only configuration contract. + /// + public interface IReadableConfiguration + { + /// + /// Gets the access token. + /// + /// Access token. + string AccessToken { get; } + + /// + /// Gets the API key. + /// + /// API key. + IDictionary ApiKey { get; } + + /// + /// Gets the API key prefix. + /// + /// API key prefix. + IDictionary ApiKeyPrefix { get; } + + /// + /// Gets the base path. + /// + /// Base path. + string BasePath { get; } + + /// + /// Gets the date time format. + /// + /// Date time foramt. + string DateTimeFormat { get; } + + /// + /// Gets the default header. + /// + /// Default header. + IDictionary DefaultHeader { get; } + + /// + /// Gets the temp folder path. + /// + /// Temp folder path. + string TempFolderPath { get; } + + /// + /// Gets the HTTP connection timeout (in milliseconds) + /// + /// HTTP connection timeout. + int Timeout { get; } + + /// + /// Gets the user agent. + /// + /// User agent. + string UserAgent { get; } + + /// + /// Gets the username. + /// + /// Username. + string Username { get; } + + /// + /// Gets the password. + /// + /// Password. + string Password { get; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + string GetApiKeyWithPrefix(string apiKeyIdentifier); + } +} diff --git a/src/main/resources/handlebars/csharp-471/JsonSubTypesTests.mustache b/src/main/resources/handlebars/csharp-471/JsonSubTypesTests.mustache new file mode 100644 index 0000000000..9b1f66624d --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/JsonSubTypesTests.mustache @@ -0,0 +1,125 @@ +{{>partial_header}} + +using System.Collections.Generic; +using System.Linq; +using JsonSubTypes; +using Newtonsoft.Json; +using NUnit.Framework; + +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.{{modelPackage}}; +using {{packageName}}.Client; + +namespace {{packageName}}.Test.Client +{ + public class JsonSubTypesTests + { + [Test] + public void TestSimpleJsonSubTypesExample() + { + var annimal = + JsonConvert.DeserializeObject("{\"Kind\":\"Dog\",\"Breed\":\"Jack Russell Terrier\"}"); + Assert.AreEqual("Jack Russell Terrier", (annimal as Dog)?.Breed); + } + + [Test] + public void DeserializeObjectWithCustomMapping() + { + var annimal = + JsonConvert.DeserializeObject("{\"Sound\":\"Bark\",\"Breed\":\"Jack Russell Terrier\"}"); + Assert.AreEqual("Jack Russell Terrier", (annimal as Dog2)?.Breed); + } + + [Test] + public void DeserializeObjectMappingByPropertyPresence() + { + string json = + "[{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," + + "{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," + + "{\"Skill\":\"Painter\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}]"; + + + var persons = JsonConvert.DeserializeObject>(json); + Assert.AreEqual("Painter", (persons.Last() as Artist)?.Skill); + } + } + + [JsonConverter(typeof(JsonSubtypes), "Kind")] + public interface IAnimal + { + string Kind { get; } + } + + public class Dog : IAnimal + { + public Dog() + { + Kind = "Dog"; + } + + public string Kind { get; } + public string Breed { get; set; } + } + + class Cat : IAnimal + { + public Cat() + { + Kind = "Cat"; + } + + public string Kind { get; } + bool Declawed { get; set; } + } + + [JsonConverter(typeof(JsonSubtypes), "Sound")] + [JsonSubtypes.KnownSubType(typeof(Dog2), "Bark")] + [JsonSubtypes.KnownSubType(typeof(Cat2), "Meow")] + public class Animal2 + { + public virtual string Sound { get; } + public string Color { get; set; } + } + + public class Dog2 : Animal2 + { + public Dog2() + { + Sound = "Bark"; + } + + public override string Sound { get; } + public string Breed { get; set; } + } + + public class Cat2 : Animal2 + { + public Cat2() + { + Sound = "Meow"; + } + + public override string Sound { get; } + public bool Declawed { get; set; } + } + + [JsonConverter(typeof(JsonSubtypes))] + [JsonSubtypes.KnownSubTypeWithProperty(typeof(Employee), "JobTitle")] + [JsonSubtypes.KnownSubTypeWithProperty(typeof(Artist), "Skill")] + public class Person + { + public string FirstName { get; set; } + public string LastName { get; set; } + } + + public class Employee : Person + { + public string Department { get; set; } + public string JobTitle { get; set; } + } + + public class Artist : Person + { + public string Skill { get; set; } + } +} diff --git a/src/main/resources/handlebars/csharp-471/Project.mustache b/src/main/resources/handlebars/csharp-471/Project.mustache new file mode 100644 index 0000000000..76e891feca --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/Project.mustache @@ -0,0 +1,58 @@ + + + + + net471 + {{packageName}} + {{packageName}} + Library + 1.0.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/README.mustache b/src/main/resources/handlebars/csharp-471/README.mustache new file mode 100644 index 0000000000..68fc1f23f5 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/README.mustache @@ -0,0 +1,184 @@ +# {{packageName}} - the C# library for the {{appName}} + +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +This C# SDK is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: + +- API version: {{appVersion}} +- SDK version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + + +## Frameworks supported +- .NET 4.7.1 or later + + +## Dependencies +- [RestSharp](https://www.nuget.org/packages/RestSharp) - 111.4.1 or later +- [Json.NET](https://www.nuget.org/packages/Newtonsoft.Json/) - 7.0.0 or later +- [JsonSubTypes](https://www.nuget.org/packages/JsonSubTypes/) - 1.2.0 or later + +The DLLs included in the package may not be the latest version. We recommend using [NuGet](https://docs.nuget.org/consume/installing-nuget) to obtain the latest version of the packages: +``` +Install-Package RestSharp +Install-Package Newtonsoft.Json +Install-Package JsonSubTypes +``` + +NOTE: RestSharp versions greater than 105.1.0 have a bug which causes file uploads to fail. See [RestSharp#742](https://github.com/restsharp/RestSharp/issues/742) + + +## Installation + +Run the following commands to generate the DLL +``` +cd src/{{packageName}} +dotnet restore +dotnet build +``` + +Then include the DLL (under the `bin` folder) in the C# project, and use the namespaces: +```csharp +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.Client; +using {{packageName}}.{{modelPackage}}; +``` + + +## Packaging + +A `.nuspec` is included with the project. You can follow the Nuget quickstart to [create](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#create-the-package) and [publish](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#publish-the-package) packages. + +This `.nuspec` uses placeholders from the `.csproj`, so build the `.csproj` directly: + +``` +nuget pack -Build -OutputDirectory out {{packageName}}.csproj +``` + +Then, publish to a [local feed](https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds) or [other host](https://docs.microsoft.com/en-us/nuget/hosting-packages/overview) and consume the new package via Nuget as usual. + + + +## Getting Started + +```csharp +using System; +using System.Diagnostics; +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.Client; +using {{packageName}}.{{modelPackage}}; + +namespace Example +{ + public class {{operationId}}Example + { + public void main() + { +{{#apiInfo}}{{#apis}}{{#@first}}{{#operations}}{{#operation}}{{#@first}} + {{#hasAuthMethods}} + {{#authMethods}} + {{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + Configuration.Default.Username = "YOUR_USERNAME"; + Configuration.Default.Password = "YOUR_PASSWORD"; + {{/isBasic}} + {{#isApiKey}} + // Configure API key authorization: {{{name}}} + Configuration.Default.ApiKey.Add("{{{keyParamName}}}", "YOUR_API_KEY"); + // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed + // Configuration.Default.ApiKeyPrefix.Add("{{{keyParamName}}}", "Bearer"); + {{/isApiKey}} + {{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + Configuration.Default.AccessToken = "YOUR_ACCESS_TOKEN"; + {{/isOAuth}} + {{/authMethods}} + + {{/hasAuthMethods}} + var apiInstance = new {{classname}}(); + {{#allParams}} + {{#isPrimitiveType}} + var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + var {{paramName}} = new {{{dataType}}}(); // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{/allParams}} + + try + { + {{#summary}} + // {{{.}}} + {{/summary}} + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + Debug.WriteLine(result);{{/returnType}} + } + catch (Exception e) + { + Debug.Print("Exception when calling {{classname}}.{{operationId}}: " + e.Message ); + } +{{/@first}}{{/operation}}{{/operations}}{{/@first}}{{/apis}}{{/apiInfo}} + } + } +} +``` + + +## Documentation for API Endpoints + +All URIs are relative to *{{{basePath}}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + + +## Documentation for Models + +{{#modelPackage}} +{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} +{{/modelPackage}} +{{^modelPackage}} +No model defined in this package +{{/modelPackage}} + + +## Documentation for Authorization + +{{^authMethods}} +All endpoints do not require authorization. +{{/authMethods}} +{{#authMethods}} +{{#last}} +Authentication schemes defined for the API: +{{/last}} +{{/authMethods}} +{{#authMethods}} + +### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#each scopes}} - {{@key}}: {{this}} +{{/each}} +{{/isOAuth}} + +{{/authMethods}} diff --git a/src/main/resources/handlebars/csharp-471/ReadOnlyDictionary.mustache b/src/main/resources/handlebars/csharp-471/ReadOnlyDictionary.mustache new file mode 100644 index 0000000000..1299b2436b --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/ReadOnlyDictionary.mustache @@ -0,0 +1,137 @@ +{{>partial_header}} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace {{packageName}}.Client +{ + public class ReadOnlyDictionary : IDictionary + { + private IDictionary _dictionaryImplementation; + public IEnumerator> GetEnumerator() + { + return _dictionaryImplementation.GetEnumerator(); + } + + public ReadOnlyDictionary() + { + _dictionaryImplementation = new Dictionary(); + } + + public ReadOnlyDictionary(IDictionary dictionaryImplementation) + { + if (dictionaryImplementation == null) throw new ArgumentNullException("dictionaryImplementation"); + _dictionaryImplementation = dictionaryImplementation; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable) _dictionaryImplementation).GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + throw new ReadonlyOperationException("This instance is readonly."); + } + + public void Clear() + { + throw new ReadonlyOperationException("This instance is readonly."); + } + + public bool Contains(KeyValuePair item) + { + return _dictionaryImplementation.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + _dictionaryImplementation.CopyTo(array, arrayIndex); + } + + public bool Remove(KeyValuePair item) + { + throw new ReadonlyOperationException("This instance is readonly."); + } + + public int Count + { + get { return _dictionaryImplementation.Count; } + } + + public bool IsReadOnly + { + get { return true; } + } + + public void Add(T key, K value) + { + throw new ReadonlyOperationException("This instance is readonly."); + } + + public bool ContainsKey(T key) + { + return _dictionaryImplementation.ContainsKey(key); + } + + public bool Remove(T key) + { + throw new ReadonlyOperationException("This instance is readonly."); + } + + public bool TryGetValue(T key, out K value) + { + return _dictionaryImplementation.TryGetValue(key, out value); + } + + public K this[T key] + { + get { return _dictionaryImplementation[key]; } + set + { + throw new ReadonlyOperationException("This instance is readonly."); + + } + } + + public ICollection Keys + { + get { return _dictionaryImplementation.Keys; } + } + + public ICollection Values + { + get { return _dictionaryImplementation.Values; } + } + } + + [Serializable] + public class ReadonlyOperationException : Exception + { + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public ReadonlyOperationException() + { + } + + public ReadonlyOperationException(string message) : base(message) + { + } + + public ReadonlyOperationException(string message, Exception inner) : base(message, inner) + { + } + + protected ReadonlyOperationException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { + } + } +} diff --git a/src/main/resources/handlebars/csharp-471/Solution.mustache b/src/main/resources/handlebars/csharp-471/Solution.mustache new file mode 100644 index 0000000000..0935c992dd --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/Solution.mustache @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio {{^netStandard}}2012{{/netStandard}}{{#netStandard}}14{{/netStandard}} +VisualStudioVersion = {{^netStandard}}12.0.0.0{{/netStandard}}{{#netStandard}}14.0.25420.1{{/netStandard}} +MinimumVisualStudioVersion = {{^netStandard}}10.0.0.1{{/netStandard}}{{#netStandard}}10.0.40219.1{{/netStandard}} +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{packageName}}", "src{{backslash}}{{packageName}}{{backslash}}{{packageName}}.csproj", "{{packageGuid}}" +EndProject +{{^excludeTests}}Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{testPackageName}}", "src{{backslash}}{{testPackageName}}{{backslash}}{{testPackageName}}.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}" +EndProject +{{/excludeTests}}Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {{packageGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {{packageGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU + {{packageGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU + {{packageGuid}}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/SwaggerDateConverter.mustache b/src/main/resources/handlebars/csharp-471/SwaggerDateConverter.mustache new file mode 100644 index 0000000000..4bbf0cbb73 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/SwaggerDateConverter.mustache @@ -0,0 +1,21 @@ +{{>partial_header}} +using Newtonsoft.Json.Converters; + +namespace {{packageName}}.Client +{ + /// + /// Formatter for 'date' swagger formats ss defined by full-date - RFC3339 + /// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types + /// + public class SwaggerDateConverter : IsoDateTimeConverter + { + /// + /// Initializes a new instance of the class. + /// + public SwaggerDateConverter() + { + // full-date = date-fullyear "-" date-month "-" date-mday + DateTimeFormat = "yyyy-MM-dd"; + } + } +} diff --git a/src/main/resources/handlebars/csharp-471/TestProject.mustache b/src/main/resources/handlebars/csharp-471/TestProject.mustache new file mode 100644 index 0000000000..a342749bb3 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/TestProject.mustache @@ -0,0 +1,52 @@ + + + + + net471 + {{testPackageName}} + {{testPackageName}} + Library + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + diff --git a/src/main/resources/handlebars/csharp-471/api.mustache b/src/main/resources/handlebars/csharp-471/api.mustache new file mode 100644 index 0000000000..b85ea7e72e --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/api.mustache @@ -0,0 +1,487 @@ +{{>partial_header}} +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +{{#netStandard}} +using RestSharp.Portable; +{{/netStandard}} +{{^netStandard}} +using RestSharp; +{{/netStandard}} +using {{packageName}}.Client; +{{#hasImport}}using {{packageName}}.{{modelPackage}}; +{{/hasImport}} + +namespace {{packageName}}.{{apiPackage}} +{ + {{#operations}} + /// + /// Represents a collection of functions to interact with the API endpoints + /// + {{>visibility}} interface {{interfacePrefix}}{{classname}} : IApiAccessor + { + #region Synchronous Operations + {{#operation}} + {{#contents}} + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// {{#returnType}}{{returnType}}{{/returnType}} + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}} ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// ApiResponse of {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Object(void){{/returnType}} + ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> {{operationId}}WithHttpInfo ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + {{/contents}} + {{/operation}} + #endregion Synchronous Operations + {{#supportsAsync}} + #region Asynchronous Operations + {{#operation}} + {{#contents}} + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// Task of {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}} + {{#returnType}}System.Threading.Tasks.Task<{{{returnType}}}>{{/returnType}}{{^returnType}}System.Threading.Tasks.Task{{/returnType}} {{operationId}}Async ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// Task of ApiResponse{{#returnType}} ({{returnType}}){{/returnType}} + System.Threading.Tasks.Task> {{operationId}}AsyncWithHttpInfo ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + {{/contents}} + {{/operation}} + #endregion Asynchronous Operations + {{/supportsAsync}} + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + {{>visibility}} partial class {{classname}} : {{interfacePrefix}}{{classname}} + { + private {{packageName}}.Client.ExceptionFactory _exceptionFactory = (name, response) => null; + + /// + /// Initializes a new instance of the class. + /// + /// + public {{classname}}(String basePath) + { + this.Configuration = new {{packageName}}.Client.Configuration { BasePath = basePath }; + + ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// + /// + public {{classname}}() + { + this.Configuration = {{packageName}}.Client.Configuration.Default; + + ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// using Configuration object + /// + /// An instance of Configuration + /// + public {{classname}}({{packageName}}.Client.Configuration configuration = null) + { + if (configuration == null) // use the default one in Configuration + this.Configuration = {{packageName}}.Client.Configuration.Default; + else + this.Configuration = configuration; + + ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Gets the base path of the API client. + /// + /// The base path + public String GetBasePath() + { + return this.Configuration.ApiClient.RestClient.Options.BaseUrl.ToString(); + } + + /// + /// Sets the base path of the API client. + /// + /// The base path + [Obsolete("SetBasePath is deprecated, please do 'Configuration.ApiClient = new ApiClient(\"http://new-path\")' instead.")] + public void SetBasePath(String basePath) + { + // do nothing + } + + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + public {{packageName}}.Client.Configuration Configuration {get; set;} + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + public {{packageName}}.Client.ExceptionFactory ExceptionFactory + { + get + { + if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1) + { + throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported."); + } + return _exceptionFactory; + } + set { _exceptionFactory = value; } + } + + /// + /// Gets the default header. + /// + /// Dictionary of HTTP header + [Obsolete("DefaultHeader is deprecated, please use Configuration.DefaultHeader instead.")] + public IDictionary DefaultHeader() + { + return new {{^net35}}ReadOnly{{/net35}}Dictionary(this.Configuration.DefaultHeader); + } + + /// + /// Add default header. + /// + /// Header field name. + /// Header field value. + /// + [Obsolete("AddDefaultHeader is deprecated, please use Configuration.AddDefaultHeader instead.")] + public void AddDefaultHeader(string key, string value) + { + this.Configuration.AddDefaultHeader(key, value); + } + + {{#operation}} + {{#contents}} + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// {{#returnType}}{{returnType}}{{/returnType}} + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}} ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}) + { + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = {{operationId}}WithHttpInfo({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + return localVarResponse.Data;{{/returnType}}{{^returnType}}{{operationId}}WithHttpInfo({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}});{{/returnType}} + } + + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// ApiResponse of {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Object(void){{/returnType}} + public ApiResponse<{{#returnType}} {{{returnType}}} {{/returnType}}{{^returnType}}Object{{/returnType}}> {{operationId}}WithHttpInfo ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}) + { + {{#parameters}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) + throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"); + {{/required}} + {{/parameters}} + + var localVarPath = "{{#netStandard}}.{{/netStandard}}{{{path}}}"; + var localVarPathParams = new Dictionary(); + var localVarQueryParams = new List>(); + var localVarHeaderParams = new Dictionary(this.Configuration.DefaultHeader); + var localVarFormParams = new Dictionary(); + var localVarFileParams = new Dictionary(); + Object localVarPostBody = null; + + // to determine the Content-Type header + String[] localVarHttpContentTypes = new String[] { + {{#consumes}} + "{{{mediaType}}}"{{#hasMore}}, {{/hasMore}} + {{/consumes}} + }; + String localVarHttpContentType = this.Configuration.ApiClient.SelectHeaderContentType(localVarHttpContentTypes); + + // to determine the Accept header + String[] localVarHttpHeaderAccepts = new String[] { + {{#produces}} + "{{{mediaType}}}"{{#hasMore}},{{/hasMore}} + {{/produces}} + }; + String localVarHttpHeaderAccept = this.Configuration.ApiClient.SelectHeaderAccept(localVarHttpHeaderAccepts); + if (localVarHttpHeaderAccept != null) + localVarHeaderParams.Add("Accept", localVarHttpHeaderAccept); + + {{#pathParams}} + if ({{paramName}} != null) localVarPathParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // path parameter + {{/pathParams}} + {{#queryParams}} + if ({{paramName}} != null) localVarQueryParams.AddRange(this.Configuration.ApiClient.ParameterToKeyValuePairs("{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); // query parameter + {{/queryParams}} + {{#headerParams}} + if ({{paramName}} != null) localVarHeaderParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // header parameter + {{/headerParams}} + {{#isForm}} + {{#formParams}} + if ({{paramName}} != null) {{#isBinary}}localVarFileParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToFile("{{baseName}}", {{paramName}}));{{/isBinary}}{{^isBinary}}localVarFormParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // form parameter{{/isBinary}} + {{/formParams}} + {{/isForm}} + {{^isForm}} + {{#bodyParam}} + if ({{paramName}} != null && {{paramName}}.GetType() != typeof(byte[])) + { + localVarPostBody = this.Configuration.ApiClient.Serialize({{paramName}}); // http body (model) parameter + } + else + { + localVarPostBody = {{paramName}}; // byte array + } + {{/bodyParam}} + {{/isForm}} + {{#authMethods}} + // authentication ({{name}}) required + {{#isApiKey}} + {{#isKeyInHeader}} + if (!String.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + { + localVarHeaderParams["{{keyParamName}}"] = this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"); + } + {{/isKeyInHeader}} + {{#isKeyInQuery}} + if (!String.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + { + localVarQueryParams.AddRange(this.Configuration.ApiClient.ParameterToKeyValuePairs("", "{{keyParamName}}", this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))); + } + {{/isKeyInQuery}} + {{/isApiKey}} + {{#isBasic}} + // http basic authentication required + if (!String.IsNullOrEmpty(this.Configuration.Username) || !String.IsNullOrEmpty(this.Configuration.Password)) + { + localVarHeaderParams["Authorization"] = "Basic " + ApiClient.Base64Encode(this.Configuration.Username + ":" + this.Configuration.Password); + } + {{/isBasic}} + {{#isBearer}} + // bearer required + if (!String.IsNullOrEmpty(this.Configuration.AccessToken)) + { + localVarHeaderParams["Authorization"] = "Bearer " + this.Configuration.AccessToken; + } + {{/isBearer}} + {{#isOAuth}} + // oauth required + if (!String.IsNullOrEmpty(this.Configuration.AccessToken)) + { + localVarHeaderParams["Authorization"] = "Bearer " + this.Configuration.AccessToken; + } + {{/isOAuth}} + {{/authMethods}} + + // make the HTTP request + RestResponse localVarResponse = (RestResponse) this.Configuration.ApiClient.CallApi(localVarPath, + Method.{{#lambda.capitalise}}{{httpMethod}}{{/lambda.capitalise}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarFileParams, + localVarPathParams, localVarHttpContentType); + + int localVarStatusCode = (int) localVarResponse.StatusCode; + + if (ExceptionFactory != null) + { + Exception exception = ExceptionFactory("{{operationId}}", localVarResponse); + if (exception != null) throw exception; + } + + {{#returnType}} + return new ApiResponse<{{{returnType}}}>(localVarStatusCode, + localVarResponse.Headers.ToDictionary(x => x.{{^netStandard}}Name{{/netStandard}}{{#netStandard}}Key{{/netStandard}}, x => string.Join(",", x.Value)), + ({{{returnType}}}) this.Configuration.ApiClient.Deserialize(localVarResponse, typeof({{#returnContainer}}{{{returnContainer}}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}}))); + {{/returnType}} + {{^returnType}} + return new ApiResponse(localVarStatusCode, + localVarResponse.Headers.ToDictionary(x => x.{{^netStandard}}Name{{/netStandard}}{{#netStandard}}Key{{/netStandard}}, x => string.Join(",", x.Value)), + null); + {{/returnType}} + } + + {{#supportsAsync}} + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// Task of {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}} + {{#returnType}}public async System.Threading.Tasks.Task<{{{returnType}}}>{{/returnType}}{{^returnType}}public async System.Threading.Tasks.Task{{/returnType}} {{operationId}}Async ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}) + { + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = await {{operationId}}AsyncWithHttpInfo({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + return localVarResponse.Data;{{/returnType}}{{^returnType}}await {{operationId}}AsyncWithHttpInfo({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}});{{/returnType}} + + } + + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#parameters}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/parameters}}/// Task of ApiResponse{{#returnType}} ({{returnType}}){{/returnType}} + public async System.Threading.Tasks.Task> {{operationId}}AsyncWithHttpInfo ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}) + { + {{#parameters}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) + throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"); + {{/required}} + {{/parameters}} + + var localVarPath = "{{#netStandard}}.{{/netStandard}}{{{path}}}"; + var localVarPathParams = new Dictionary(); + var localVarQueryParams = new List>(); + var localVarHeaderParams = new Dictionary(this.Configuration.DefaultHeader); + var localVarFormParams = new Dictionary(); + var localVarFileParams = new Dictionary(); + Object localVarPostBody = null; + + // to determine the Content-Type header + String[] localVarHttpContentTypes = new String[] { + {{#consumes}} + "{{{mediaType}}}"{{#hasMore}}, {{/hasMore}} + {{/consumes}} + }; + String localVarHttpContentType = this.Configuration.ApiClient.SelectHeaderContentType(localVarHttpContentTypes); + + // to determine the Accept header + String[] localVarHttpHeaderAccepts = new String[] { + {{#produces}} + "{{{mediaType}}}"{{#hasMore}},{{/hasMore}} + {{/produces}} + }; + String localVarHttpHeaderAccept = this.Configuration.ApiClient.SelectHeaderAccept(localVarHttpHeaderAccepts); + if (localVarHttpHeaderAccept != null) + localVarHeaderParams.Add("Accept", localVarHttpHeaderAccept); + + {{#pathParams}} + if ({{paramName}} != null) localVarPathParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // path parameter + {{/pathParams}} + {{#queryParams}} + if ({{paramName}} != null) localVarQueryParams.AddRange(this.Configuration.ApiClient.ParameterToKeyValuePairs("{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); // query parameter + {{/queryParams}} + {{#headerParams}} + if ({{paramName}} != null) localVarHeaderParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // header parameter + {{/headerParams}} + {{#isForm}} + {{#formParams}} + if ({{paramName}} != null) {{#isBinary}}localVarFileParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToFile("{{baseName}}", {{paramName}}));{{/isBinary}}{{^isBinary}}localVarFormParams.Add("{{baseName}}", this.Configuration.ApiClient.ParameterToString({{paramName}})); // form parameter{{/isBinary}} + {{/formParams}} + {{/isForm}} + {{^isForm}} + {{#bodyParam}} + if ({{paramName}} != null && {{paramName}}.GetType() != typeof(byte[])) + { + localVarPostBody = this.Configuration.ApiClient.Serialize({{paramName}}); // http body (model) parameter + } + else + { + localVarPostBody = {{paramName}}; // byte array + } + {{/bodyParam}} + {{/isForm}} + {{#authMethods}} + // authentication ({{name}}) required + {{#isApiKey}} + {{#isKeyInHeader}} + if (!String.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + { + localVarHeaderParams["{{keyParamName}}"] = this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"); + } + {{/isKeyInHeader}} + {{#isKeyInQuery}} + if (!String.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + { + localVarQueryParams.AddRange(this.Configuration.ApiClient.ParameterToKeyValuePairs("", "{{keyParamName}}", this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))); + } + {{/isKeyInQuery}} + {{/isApiKey}} + {{#isBasic}} + // http basic authentication required + if (!String.IsNullOrEmpty(this.Configuration.Username) || !String.IsNullOrEmpty(this.Configuration.Password)) + { + localVarHeaderParams["Authorization"] = "Basic " + ApiClient.Base64Encode(this.Configuration.Username + ":" + this.Configuration.Password); + } + {{/isBasic}} + {{#isBearer}} + // bearer required + if (!String.IsNullOrEmpty(this.Configuration.AccessToken)) + { + localVarHeaderParams["Authorization"] = "Bearer " + this.Configuration.AccessToken; + } + {{/isBearer}} + {{#isOAuth}} + // oauth required + if (!String.IsNullOrEmpty(this.Configuration.AccessToken)) + { + localVarHeaderParams["Authorization"] = "Bearer " + this.Configuration.AccessToken; + } + {{/isOAuth}} + {{/authMethods}} + + // make the HTTP request + RestResponse localVarResponse = (RestResponse) await this.Configuration.ApiClient.CallApiAsync(localVarPath, + Method.{{#lambda.capitalise}}{{httpMethod}}{{/lambda.capitalise}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarFileParams, + localVarPathParams, localVarHttpContentType); + + int localVarStatusCode = (int) localVarResponse.StatusCode; + + if (ExceptionFactory != null) + { + Exception exception = ExceptionFactory("{{operationId}}", localVarResponse); + if (exception != null) throw exception; + } + + {{#returnType}} + return new ApiResponse<{{{returnType}}}>(localVarStatusCode, + localVarResponse.Headers.ToDictionary(x => x.{{^netStandard}}Name{{/netStandard}}{{#netStandard}}Key{{/netStandard}}, x => string.Join(",", x.Value)), + ({{{returnType}}}) this.Configuration.ApiClient.Deserialize(localVarResponse, typeof({{#returnContainer}}{{{returnContainer}}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}}))); + {{/returnType}} + {{^returnType}} + return new ApiResponse(localVarStatusCode, + localVarResponse.Headers.ToDictionary(x => x.{{^netStandard}}Name{{/netStandard}}{{#netStandard}}Key{{/netStandard}}, x => string.Join(",", x.Value)), + null); + {{/returnType}} + } + + {{/supportsAsync}} + {{/contents}} + {{/operation}} + } + {{/operations}} +} diff --git a/src/main/resources/handlebars/csharp-471/api_doc.mustache b/src/main/resources/handlebars/csharp-471/api_doc.mustache new file mode 100644 index 0000000000..4ed1ca0fdb --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/api_doc.mustache @@ -0,0 +1,108 @@ +# {{packageName}}.{{apiPackage}}.{{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{{basePath}}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} +{{#contents}} +{{#@first}} + +# **{{{operationId}}}** +> {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}} ({{#parameters}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = null{{/optionalMethodArgument}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/parameters}}) + +{{{summary}}}{{#notes}} + +{{{notes}}}{{/notes}} + +### Example +```csharp +using System; +using System.Diagnostics; +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.Client; +using {{packageName}}.{{modelPackage}}; + +namespace Example +{ + public class {{operationId}}Example + { + public void main() + { + {{#hasAuthMethods}} + {{#authMethods}} + {{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + Configuration.Default.Username = "YOUR_USERNAME"; + Configuration.Default.Password = "YOUR_PASSWORD"; + {{/isBasic}} + {{#isApiKey}} + // Configure API key authorization: {{{name}}} + Configuration.Default.AddApiKey("{{{keyParamName}}}", "YOUR_API_KEY"); + // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed + // Configuration.Default.AddApiKeyPrefix("{{{keyParamName}}}", "Bearer"); + {{/isApiKey}} + {{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + Configuration.Default.AccessToken = "YOUR_ACCESS_TOKEN"; + {{/isOAuth}} + {{/authMethods}} + + {{/hasAuthMethods}} + var apiInstance = new {{classname}}(); + {{#parameters}} + {{#isPrimitiveType}} + var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + var {{paramName}} = new {{{dataType}}}(); // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{/parameters}} + + try + { + {{#summary}} + // {{{.}}} + {{/summary}} + {{#returnType}}{{returnType}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}});{{#returnType}} + Debug.WriteLine(result);{{/returnType}} + } + catch (Exception e) + { + Debug.Print("Exception when calling {{classname}}.{{operationId}}: " + e.Message ); + } + } + } +} +``` + +### Parameters +{{^parameters}}This endpoint does not need any parameter.{{/parameters}}{{#parameters}}{{#@last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/@last}}{{/parameters}} +{{#parameters}} **{{paramName}}** | {{#isBinary}}**{{dataType}}**{{/isBinary}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isBinary}}[**{{dataType}}**]({{#isContainer}}{{baseType}}{{/isContainer}}{{^isContainer}}{{dataType}}{{/isContainer}}.md){{/isBinary}}{{/isPrimitiveType}}| {{description}} | {{^required}}[optional] {{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} +{{/parameters}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^@last}}, {{/@last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +{{/@first}} +{{/contents}} +{{/operation}} +{{/operations}} diff --git a/src/main/resources/handlebars/csharp-471/api_test.mustache b/src/main/resources/handlebars/csharp-471/api_test.mustache new file mode 100644 index 0000000000..e24939db5d --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/api_test.mustache @@ -0,0 +1,75 @@ +{{>partial_header}} +using System; +using System.IO; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using RestSharp; +using NUnit.Framework; + +using {{packageName}}.Client; +using {{packageName}}.{{apiPackage}}; +{{#hasImport}}using {{packageName}}.{{modelPackage}}; +{{/hasImport}} + +namespace {{packageName}}.Test +{ + /// + /// Class for testing {{classname}} + /// + /// + /// This file is automatically generated by Swagger Codegen. + /// Please update the test case below to test the API endpoint. + /// + [TestFixture] + public class {{classname}}Tests + { + private {{classname}} instance; + + /// + /// Setup before each unit test + /// + [SetUp] + public void Init() + { + instance = new {{classname}}(); + } + + /// + /// Clean up after each unit test + /// + [TearDown] + public void Cleanup() + { + + } + + /// + /// Test an instance of {{classname}} + /// + [Test] + public void {{operationId}}InstanceTest() + { + // TODO uncomment below to test 'IsInstanceOfType' {{classname}} + //Assert.IsInstanceOfType(typeof({{classname}}), instance, "instance is a {{classname}}"); + } + + {{#operations}}{{#operation}}{{#contents}}{{#@first}} + /// + /// Test {{operationId}} + /// + [Test] + public void {{operationId}}Test() + { + // TODO uncomment below to test the method and replace null with proper value + {{#parameters}} + //{{{dataType}}} {{paramName}} = null; + {{/parameters}} + //{{#returnType}}var response = {{/returnType}}instance.{{operationId}}({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); + {{#returnType}}//Assert.IsInstanceOf<{{{returnType}}}> (response, "response is {{{returnType}}}");{{/returnType}} + } + {{/@first}}{{/contents}}{{/operation}}{{/operations}} + } + +} diff --git a/src/main/resources/handlebars/csharp-471/compile-mono.sh.mustache b/src/main/resources/handlebars/csharp-471/compile-mono.sh.mustache new file mode 100644 index 0000000000..3e9cb139af --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/compile-mono.sh.mustache @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# + +frameworkVersion={{targetFrameworkNuget}} + +# sdk must match installed framworks under PREFIX/lib/mono/[value] +sdk={{x-mcs-sdk}} + +# langversion refers to C# language features. see man mcs for details. +langversion=${sdk} +nuget_cmd=nuget + +# Match against our known SDK possibilities +case "${sdk}" in + 4) + langversion=4 + ;; + 4.5*) + langversion=5 + ;; + 4.6*) + langversion=6 + ;; + 4.7*) + langversion=7 # ignoring 7.1 for now. + ;; + *) + langversion=6 + ;; +esac + +echo "[INFO] Target framework: ${frameworkVersion}" + +if ! type nuget &>/dev/null; then + echo "[INFO] Download nuget and packages" + wget -nc https://dist.nuget.org/win-x86-commandline/latest/nuget.exe; + nuget_cmd="mono nuget.exe" +fi + +mozroots --import --sync +${nuget_cmd} install src/{{packageName}}/packages.config -o packages; + +echo "[INFO] Copy DLLs to the 'bin' folder" +mkdir -p bin; +cp packages/Newtonsoft.Json.13.0.3/lib/{{targetFrameworkNuget}}/Newtonsoft.Json.dll bin/Newtonsoft.Json.dll; +cp packages/RestSharp.111.4.1/lib/{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}/RestSharp.dll bin/RestSharp.dll; +cp packages/JsonSubTypes.1.2.0/lib/{{targetFrameworkNuget}}/JsonSubTypes.dll bin/JsonSubTypes.dll +cp packages/System.Net.Http.4.3.4/lib/net46/System.Net.Http.dll bin/System.Net.Http.dll +{{#generatePropertyChanged}} +cp packages/Fody.1.29.4/Fody.dll bin/Fody.dll +cp packages/PropertyChanged.Fody.1.51.3/PropertyChanged.Fody.dll bin/PropertyChanged.Fody.dll +cp packages/PropertyChanged.Fody.1.51.3/Lib/dotnet/PropertyChanged.dll bin/PropertyChanged.dll +{{/generatePropertyChanged}} + +echo "[INFO] Run 'mcs' to build bin/{{{packageName}}}.dll" +mcs -langversion:${langversion} -sdk:${sdk} -r:bin/Newtonsoft.Json.dll,bin/JsonSubTypes.dll,\ +{{#generatePropertyChanged}} +bin/Fody.dll,\ +bin/PropertyChanged.Fody.dll,\ +bin/PropertyChanged.dll,\ +{{/generatePropertyChanged}} +bin/RestSharp.dll,\ +bin/System.Net.Http.dll,\ +System.ComponentModel.DataAnnotations.dll,\ +System.Runtime.Serialization.dll \ +-target:library \ +-out:bin/{{packageName}}.dll \ +-recurse:'src/{{packageName}}/*.cs' \ +-doc:bin/{{packageName}}.xml \ +-platform:anycpu + +if [ $? -ne 0 ] +then + echo "[ERROR] Compilation failed with exit code $?" + exit 1 +else + echo "[INFO] bin/{{{packageName}}}.dll was created successfully" +fi diff --git a/src/main/resources/handlebars/csharp-471/compile.mustache b/src/main/resources/handlebars/csharp-471/compile.mustache new file mode 100644 index 0000000000..42f87e7d27 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/compile.mustache @@ -0,0 +1,28 @@ +:: Generated by: https://github.com/swagger-api/swagger-codegen.git +:: + +@echo off + +{{#supportsAsync}} +SET CSCPATH=%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319 +{{/supportsAsync}} +{{^supportsAsync}} +SET CSCPATH=%SYSTEMROOT%\Microsoft.NET\Framework\v3.5 +{{/supportsAsync}} + +if not exist ".\nuget.exe" powershell -Command "(new-object System.Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '.\nuget.exe')" +.\nuget.exe install src{{backslash}}{{packageName}}\packages.config -o packages + +if not exist ".\bin" mkdir bin + +copy packages\Newtonsoft.Json.13.0.3\lib{{backslash}}{{targetFrameworkNuget}}\Newtonsoft.Json.dll bin\Newtonsoft.Json.dll +copy packages\JsonSubTypes.1.2.0\lib{{backslash}}{{targetFrameworkNuget}}\JsonSubTypes.dll bin\JsonSubTypes.dll +copy packages\RestSharp.111.4.1\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll bin\RestSharp.dll +copy packages/System.Net.Http.4.3.4/lib/net46/System.Net.Http.dll bin/System.Net.Http.dll +{{#generatePropertyChanged}} +copy packages\Fody.1.29.4\Fody.dll bin\Fody.dll +copy packages\PropertyChanged.Fody.1.51.3\PropertyChanged.Fody.dll bin\PropertyChanged.Fody.dll +copy packages\PropertyChanged.Fody.1.51.3\Lib\dotnet\PropertyChanged.dll bin\PropertyChanged.dll +{{/generatePropertyChanged}} +%CSCPATH%\csc /reference:bin\Newtonsoft.Json.dll;bin\JsonSubTypes.dll;bin\RestSharp.dll;System.ComponentModel.DataAnnotations.dll {{#generatePropertyChanged}}/r:bin\Fody.dll;bin\PropertyChanged.Fody.dll;bin\PropertyChanged.dll{{/generatePropertyChanged}} /target:library /out:bin{{backslash}}{{packageName}}.dll /recurse:src{{backslash}}{{packageName}}\*.cs /doc:bin{{backslash}}{{packageName}}.xml + diff --git a/src/main/resources/handlebars/csharp-471/enumClass.mustache b/src/main/resources/handlebars/csharp-471/enumClass.mustache new file mode 100644 index 0000000000..6376df7590 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/enumClass.mustache @@ -0,0 +1,17 @@ + /// + /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + [JsonConverter(typeof(StringEnumConverter))] + {{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} + { + {{#allowableValues}}{{#enumVars}} + /// + /// Enum {{name}} for {{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}} + /// + [EnumMember(Value = {{#value}}{{#isLong}}"{{/isLong}}{{#isInteger}}"{{/isInteger}}{{#isFloat}}"{{/isFloat}}{{#isDouble}}"{{/isDouble}}{{{value}}}{{#isLong}}"{{/isLong}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isFloat}}"{{/isFloat}}{{/value}}{{^value}}null{{/value}})] + {{name}} {{#value}}{{#isLong}} = {{{value}}}{{/isLong}}{{#isInteger}} = {{{value}}}{{/isInteger}}{{^isInteger}} = {{@index}}{{/isInteger}}{{/value}}{{^value}}null{{/value}}{{^@last}}, + {{/@last}}{{/enumVars}}{{/allowableValues}} + } diff --git a/src/main/resources/handlebars/csharp-471/git_push.sh.mustache b/src/main/resources/handlebars/csharp-471/git_push.sh.mustache new file mode 100755 index 0000000000..f65b794638 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/src/main/resources/handlebars/csharp-471/gitignore.mustache b/src/main/resources/handlebars/csharp-471/gitignore.mustache new file mode 100644 index 0000000000..17302c93bf --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/gitignore.mustache @@ -0,0 +1,186 @@ +# Ref: https://gist.github.com/kmorcinek/2710267 +# Download this file using PowerShell v3 under Windows with the following comand +# Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore + +# User-specific files +*.suo +*.user +*.sln.docstates +./nuget + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# OS generated files # +.DS_Store* +ehthumbs.db +Icon? +Thumbs.db + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings +modulesbin/ +tempbin/ + +# EPiServer Site file (VPP) +AppData/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# vim +*.txt~ +*.swp +*.swo + +# svn +.svn + +# SQL Server files +**/App_Data/*.mdf +**/App_Data/*.ldf +**/App_Data/*.sdf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +# SASS Compiler cache +.sass-cache + +# Visual Studio 2014 CTP +**/*.sln.ide diff --git a/src/main/resources/handlebars/csharp-471/interface.mustache b/src/main/resources/handlebars/csharp-471/interface.mustache new file mode 100644 index 0000000000..9158acb850 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/interface.mustache @@ -0,0 +1,12 @@ +/// +/// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} +/// +public interface {{{classname}}} +{ + +{{#vendorExtensions}} +{{#x-discriminator-type-getter}} + {{x-discriminator-type}} {{x-discriminator-type-getter}}(); +{{/x-discriminator-type-getter}} +{{/vendorExtensions}} +} diff --git a/src/main/resources/handlebars/csharp-471/model.mustache b/src/main/resources/handlebars/csharp-471/model.mustache new file mode 100644 index 0000000000..7d562abbe7 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/model.mustache @@ -0,0 +1,44 @@ +{{>partial_header}} +{{^x-is-composed-model}} +using System; +using System.Linq; +using System.IO; +using System.Text; +{{^netStandard}} +using System.Text.RegularExpressions; +{{/netStandard}} +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +{{#models}} +{{#model}} +{{#discriminator}} +using JsonSubTypes; +{{/discriminator}} +{{/model}} +{{/models}} +{{^netStandard}} +{{#generatePropertyChanged}} +using PropertyChanged; +using System.ComponentModel; +{{/generatePropertyChanged}} +using System.ComponentModel.DataAnnotations; +{{/netStandard}} +using SwaggerDateConverter = {{packageName}}.Client.SwaggerDateConverter; +{{/x-is-composed-model}} +{{#models}} +{{#model}} +namespace {{packageName}}.{{modelPackage}} +{ +{{#isComposedModel}} + {{>interface}} +{{/isComposedModel}} +{{^isComposedModel}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>modelGeneric}}{{/isEnum}} +{{/isComposedModel}} +{{/model}} +{{/models}} +} diff --git a/src/main/resources/handlebars/csharp-471/modelEnum.mustache b/src/main/resources/handlebars/csharp-471/modelEnum.mustache new file mode 100644 index 0000000000..1dfb03cd35 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/modelEnum.mustache @@ -0,0 +1,19 @@ + /// + /// {{^description}}Defines {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + {{#allowableValues}}{{#enumVars}}{{#@first}}{{#isString}} + [JsonConverter(typeof(StringEnumConverter))] + {{/isString}}{{/@first}}{{/enumVars}}{{/allowableValues}} + {{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-enum-byte}}: byte{{/vendorExtensions.x-enum-byte}} + { + {{#allowableValues}}{{#enumVars}} + /// + /// Enum {{name}} for value: {{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}} + /// + {{#isString}}[EnumMember(Value = {{#value}}"{{{value}}}"{{/value}}{{^value}}null{{/value}})]{{/isString}} + {{name}}{{^isString}} = {{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}}{{/isString}}{{#isString}} = {{@index_1}}{{/isString}}{{^@last}}, + {{/@last}}{{/enumVars}}{{/allowableValues}} + }{{! NOTE: This model's enumVars is modified to look like CodegenProperty}} diff --git a/src/main/resources/handlebars/csharp-471/modelGeneric.mustache b/src/main/resources/handlebars/csharp-471/modelGeneric.mustache new file mode 100644 index 0000000000..6168a7ccb9 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/modelGeneric.mustache @@ -0,0 +1,307 @@ + /// + /// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + /// + [DataContract] + {{#discriminator}} + [JsonConverter(typeof(JsonSubtypes), "{{discriminator.propertyName}}")]{{#children}} + [JsonSubtypes.KnownSubType(typeof({{classname}}), "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}")]{{/children}} + {{/discriminator}} + {{#generatePropertyChanged}} + [ImplementPropertyChanged] + {{/generatePropertyChanged}} + {{>visibility}} partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>{{^netStandard}}{{#validatable}}, IValidatableObject{{/validatable}}{{/netStandard}}{{#interfaceModels}}{{#@first}}, {{/@first}}{{classname}}{{^@last}}, {{/@last}}{{#@last}} {{/@last}}{{/interfaceModels}} + { + {{#vars}} + {{#items.isEnum}} + {{#items}} + {{^complexType}} +{{>modelInnerEnum}} + {{/complexType}} + {{/items}} + {{/items.isEnum}} + {{#isEnum}} + {{^complexType}} +{{>modelInnerEnum}} + {{/complexType}} + {{/isEnum}} + {{#isEnum}} + /// + /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + [DataMember(Name="{{baseName}}", EmitDefaultValue={{emitDefaultValue}})] + public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; } + {{/isEnum}} + {{/vars}} + {{#hasRequired}} + {{^hasOnlyReadOnly}} + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected {{classname}}() { } + {{/hasOnlyReadOnly}} + {{/hasRequired}} + /// + /// Initializes a new instance of the class. + /// + {{#vars}} + {{^isReadOnly}} + /// {{#description}}{{description}}{{/description}}{{^description}}{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}{{/description}}{{#required}} (required){{/required}}{{#defaultValue}} (default to {{defaultValue}}){{/defaultValue}}. + {{/isReadOnly}} + {{/vars}} + {{#hasOnlyReadOnly}} + [JsonConstructorAttribute] + {{/hasOnlyReadOnly}} + public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/isEnum}} {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}default({{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/isEnum}}){{/defaultValue}}{{^@last}}, {{/@last}}{{/readWriteVars}}){{#parent}} : base({{#parentVars}}{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}{{#hasMore}}, {{/hasMore}}{{/parentVars}}){{/parent}} + { + {{#vars}} + {{^isInherited}} + {{^isReadOnly}} + {{#required}} + // to ensure "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" is required (not null) + if ({{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} == null) + { + throw new InvalidDataException("{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} is a required property for {{classname}} and cannot be null"); + } + else + { + this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + } + {{/required}} + {{/isReadOnly}} + {{/isInherited}} + {{/vars}} + {{#vars}} + {{^isInherited}} + {{^isReadOnly}} + {{^required}} + {{#defaultValue}}// use default value if no "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" provided + if ({{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} == null) + { + this.{{name}} = {{{defaultValue}}}; + } + else + { + this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + } + {{/defaultValue}} + {{^defaultValue}} +this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + {{/defaultValue}} + {{/required}} + {{/isReadOnly}} + {{/isInherited}} + {{/vars}} + } + + {{#vars}} + {{^isInherited}} + {{^isEnum}} + /// + /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// {{#description}} + /// {{description}}{{/description}} + [DataMember(Name="{{baseName}}", EmitDefaultValue={{emitDefaultValue}})]{{#isDate}} + [JsonConverter(typeof(SwaggerDateConverter))]{{/isDate}} + public {{{datatype}}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; } + {{/isEnum}} + {{/isInherited}} + + {{/vars}} + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class {{classname}} {\n"); + {{#parent}} + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); + {{/parent}} + {{#vars}} + sb.Append(" {{name}}: ").Append({{name}}).Append("\n"); + {{/vars}} + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public {{#parent}}{{^isArrayModel}}override {{/isArrayModel}}{{/parent}}{{^parent}}virtual {{/parent}}string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as {{classname}}); + } + + /// + /// Returns true if {{classname}} instances are equal + /// + /// Instance of {{classname}} to be compared + /// Boolean + public bool Equals({{classname}} input) + { + if (input == null) + return false; + + return {{#vars}}{{#parent}}base.Equals(input) && {{/parent}}{{#isNotContainer}} + ( + this.{{name}} == input.{{name}} || + (this.{{name}} != null && + this.{{name}}.Equals(input.{{name}})) + ){{#hasMore}} && {{/hasMore}}{{/isNotContainer}}{{^isNotContainer}} + ( + this.{{name}} == input.{{name}} || + this.{{name}} != null && + input.{{name}} != null && + this.{{name}}.SequenceEqual(input.{{name}}) + ){{#hasMore}} && {{/hasMore}}{{/isNotContainer}}{{/vars}}{{^vars}}{{#parent}}base.Equals(input){{/parent}}{{^parent}}false{{/parent}}{{/vars}}; + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + {{#parent}} + int hashCode = base.GetHashCode(); + {{/parent}} + {{^parent}} + int hashCode = 41; + {{/parent}} + {{#vars}} + if (this.{{name}} != null) + hashCode = hashCode * 59 + this.{{name}}.GetHashCode(); + {{/vars}} + return hashCode; + } + } +{{^netStandard}} + +{{#generatePropertyChanged}} + /// + /// Property changed event handler + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// Trigger when a property changed + /// + /// Property Name + public virtual void OnPropertyChanged(string propertyName) + { + // NOTE: property changed is handled via "code weaving" using Fody. + // Properties with setters are modified at compile time to notify of changes. + var propertyChanged = PropertyChanged; + if (propertyChanged != null) + { + propertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + +{{/generatePropertyChanged}} +{{#validatable}} +{{#discriminator}} + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + return this.BaseValidate(validationContext); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + protected IEnumerable BaseValidate(ValidationContext validationContext) + { +{{/discriminator}} +{{^discriminator}} + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { +{{/discriminator}} + {{#parent}} + {{^isArrayModel}} + {{#discriminator}} + foreach(var x in BaseValidate(validationContext)) yield return x; + {{/discriminator}} + {{/isArrayModel}} + {{/parent}} + {{#vars}} + {{#hasValidation}} + {{#maxLength}} + // {{{name}}} ({{{datatype}}}) maxLength + if(this.{{{name}}} != null && this.{{{name}}}.Length > {{maxLength}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, length must be less than {{maxLength}}.", new [] { "{{{name}}}" }); + } + + {{/maxLength}} + {{#minLength}} + // {{{name}}} ({{{datatype}}}) minLength + if(this.{{{name}}} != null && this.{{{name}}}.Length < {{minLength}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, length must be greater than {{minLength}}.", new [] { "{{{name}}}" }); + } + + {{/minLength}} + {{#maximum}} + // {{{name}}} ({{{datatype}}}) maximum + if(this.{{{name}}} > ({{{datatype}}}){{maximum}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must be a value less than or equal to {{maximum}}.", new [] { "{{{name}}}" }); + } + + {{/maximum}} + {{#minimum}} + // {{{name}}} ({{{datatype}}}) minimum + if(this.{{{name}}} < ({{{datatype}}}){{minimum}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must be a value greater than or equal to {{minimum}}.", new [] { "{{{name}}}" }); + } + + {{/minimum}} + {{#pattern}} + {{^isByteArray}} + // {{{name}}} ({{{datatype}}}) pattern + Regex regex{{{name}}} = new Regex(@"{{{vendorExtensions.x-regex}}}"{{#vendorExtensions.x-modifiers}}{{#@first}}, {{/@first}}RegexOptions.{{{.}}}{{^@last}} | {{/@last}}{{/vendorExtensions.x-modifiers}}); + if (false == regex{{{name}}}.Match(this.{{{name}}}).Success) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must match a pattern of " + regex{{{name}}}, new [] { "{{{name}}}" }); + } + + {{/isByteArray}} + {{/pattern}} + {{/hasValidation}} + {{/vars}} + yield break; + } +{{/validatable}} +{{/netStandard}} + } diff --git a/src/main/resources/handlebars/csharp-471/modelInnerEnum.mustache b/src/main/resources/handlebars/csharp-471/modelInnerEnum.mustache new file mode 100644 index 0000000000..6a3fabb10e --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/modelInnerEnum.mustache @@ -0,0 +1,21 @@ + {{^isContainer}} + /// + /// {{^description}}Defines {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + {{#isString}} + [JsonConverter(typeof(StringEnumConverter))] + {{/isString}} + {{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-enum-byte}}: byte{{/vendorExtensions.x-enum-byte}} + { + {{#allowableValues}}{{#enumVars}} + /// + /// Enum {{name}} for value: {{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}} + /// + {{#isString}}[EnumMember(Value = {{#value}}"{{{value}}}"{{/value}}{{^value}}null{{/value}})]{{/isString}} + {{name}}{{^isString}} = {{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}}{{/isString}}{{#isString}} = {{@index_1}}{{/isString}}{{^@last}}, + {{/@last}}{{/enumVars}}{{/allowableValues}} + } + {{/isContainer}} diff --git a/src/main/resources/handlebars/csharp-471/model_doc.mustache b/src/main/resources/handlebars/csharp-471/model_doc.mustache new file mode 100644 index 0000000000..0b62dadc6d --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}} +{{#model}} +# {{{packageName}}}.{{modelPackage}}.{{{classname}}} +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#parent}} +{{#parentVars}} +**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/parentVars}} +{{/parent}} +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/vars}} + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + +{{/model}} +{{/models}} diff --git a/src/main/resources/handlebars/csharp-471/model_test.mustache b/src/main/resources/handlebars/csharp-471/model_test.mustache new file mode 100644 index 0000000000..3a433b5f30 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/model_test.mustache @@ -0,0 +1,90 @@ +{{>partial_header}} + +using NUnit.Framework; + +using System; +using System.Linq; +using System.IO; +using System.Collections.Generic; +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.{{modelPackage}}; +using {{packageName}}.Client; +using System.Reflection; +using Newtonsoft.Json; + +{{#models}} +{{#model}} +namespace {{packageName}}.Test +{ + /// + /// Class for testing {{classname}} + /// + /// + /// This file is automatically generated by Swagger Codegen. + /// Please update the test case below to test the model. + /// + [TestFixture] + public class {{classname}}Tests + { + // TODO uncomment below to declare an instance variable for {{classname}} + //private {{classname}} instance; + + /// + /// Setup before each test + /// + [SetUp] + public void Init() + { + // TODO uncomment below to create an instance of {{classname}} + //instance = new {{classname}}(); + } + + /// + /// Clean up after each test + /// + [TearDown] + public void Cleanup() + { + + } + + /// + /// Test an instance of {{classname}} + /// + [Test] + public void {{classname}}InstanceTest() + { + // TODO uncomment below to test "IsInstanceOfType" {{classname}} + //Assert.IsInstanceOfType<{{classname}}> (instance, "variable 'instance' is a {{classname}}"); + } + + {{#discriminator}} + {{#children}} + /// + /// Test deserialize a {{classname}} from type {{parent}} + /// + [Test] + public void {{classname}}DeserializeFrom{{parent}}Test() + { + // TODO uncomment below to test deserialize a {{classname}} from type {{parent}} + //Assert.IsInstanceOf<{{parent}}>(JsonConvert.DeserializeObject<{{parent}}>(new {{classname}}().ToJson())); + } + {{/children}} + {{/discriminator}} + + {{#vars}} + /// + /// Test the property '{{name}}' + /// + [Test] + public void {{name}}Test() + { + // TODO unit test for the property '{{name}}' + } + {{/vars}} + + } + +} +{{/model}} +{{/models}} diff --git a/src/main/resources/handlebars/csharp-471/mono_nunit_test.mustache b/src/main/resources/handlebars/csharp-471/mono_nunit_test.mustache new file mode 100644 index 0000000000..f9d2d63018 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/mono_nunit_test.mustache @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# + +wget -nc https://dist.nuget.org/win-x86-commandline/latest/nuget.exe +mozroots --import --sync + +echo "[INFO] remove bin/Debug/SwaggerClientTest.dll" +rm src/{{{packageName}}}.Test/bin/Debug/{{{packageName}}}.Test.dll 2> /dev/null + +echo "[INFO] install NUnit runners via NuGet" +wget -nc https://dist.nuget.org/win-x86-commandline/latest/nuget.exe +mozroots --import --sync +mono nuget.exe install src/{{{packageName}}}.Test/packages.config -o packages + +echo "[INFO] Install NUnit runners via NuGet" +mono nuget.exe install NUnit.Runners -Version 2.6.4 -OutputDirectory packages + +echo "[INFO] Build the solution and run the unit test" +xbuild {{{packageName}}}.sln && \ + mono ./packages/NUnit.Runners.2.6.4/tools/nunit-console.exe src/{{{packageName}}}.Test/bin/Debug/{{{packageName}}}.Test.dll diff --git a/src/main/resources/handlebars/csharp-471/netcore_project.mustache b/src/main/resources/handlebars/csharp-471/netcore_project.mustache new file mode 100644 index 0000000000..da56d50521 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/netcore_project.mustache @@ -0,0 +1,46 @@ + + + + {{targetFrameworkNuget}} + {{packageName}} + {{packageName}} + Library + {{packageAuthors}} + {{packageCompany}} + {{packageTitle}} + {{packageDescription}} + {{packageCopyright}} + true + true + true + {{packageName}} + {{packageVersion}} + + + + {{#netStandard}} + + + {{/netStandard}} + {{^netStandard}} + + {{/netStandard}} + + + + + {{^netStandard}} + + + + + + + + + + + + {{/netStandard}} + + \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/netcore_testproject.mustache b/src/main/resources/handlebars/csharp-471/netcore_testproject.mustache new file mode 100644 index 0000000000..fd3f061d67 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/netcore_testproject.mustache @@ -0,0 +1,49 @@ + + + + {{targetFrameworkNuget}} + {{testPackageName}} + {{testPackageName}} + Library + {{packageAuthors}} + {{packageCompany}} + {{packageTitle}} + {{packageDescription}} + {{packageCopyright}} + true + true + true + {{testPackageName}} + + + + + {{#netStandard}} + + {{/netStandard}} + {{^netStandard}} + + {{/netStandard}} + + + + + {{^netStandard}} + + + + + + + + + + + + {{/netStandard}} + + + + + + \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/nuspec.mustache b/src/main/resources/handlebars/csharp-471/nuspec.mustache new file mode 100644 index 0000000000..18b64eaacb --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/nuspec.mustache @@ -0,0 +1,54 @@ + + + + + $id$ + {{packageTitle}} + + + $version$ + + + $author$ + + + $author$ + false + false + + + {{packageDescription}} + {{#termsOfService}} + {{termsOfService}} + {{/termsOfService}} + {{#licenseUrl}} + {{licenseUrl}} + {{/licenseUrl}} + + + + + + + + + {{#generatePropertyChanged}} + + + {{/generatePropertyChanged}} + + + + + + + + + {{#generatePropertyChanged}} + + {{/generatePropertyChanged}} + + + diff --git a/src/main/resources/handlebars/csharp-471/packages.config.mustache b/src/main/resources/handlebars/csharp-471/packages.config.mustache new file mode 100644 index 0000000000..0f4d16ac2a --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/packages.config.mustache @@ -0,0 +1,11 @@ + + + + + + + {{#generatePropertyChanged}} + + + {{/generatePropertyChanged}} + diff --git a/src/main/resources/handlebars/csharp-471/packages_test.config.mustache b/src/main/resources/handlebars/csharp-471/packages_test.config.mustache new file mode 100644 index 0000000000..bf461ae9b6 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/packages_test.config.mustache @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/handlebars/csharp-471/partial_header.mustache b/src/main/resources/handlebars/csharp-471/partial_header.mustache new file mode 100644 index 0000000000..b655ebb826 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/partial_header.mustache @@ -0,0 +1,13 @@ +/* + {{#appName}} + * {{{appName}}} + * + {{/appName}} + {{#appDescription}} + * {{{appDescription}}} + * + {{/appDescription}} + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ diff --git a/src/main/resources/handlebars/csharp-471/project.json.mustache b/src/main/resources/handlebars/csharp-471/project.json.mustache new file mode 100644 index 0000000000..194fdda449 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/project.json.mustache @@ -0,0 +1,12 @@ +{ + "supports": {}, + "dependencies": { + "FubarCoder.RestSharp.Portable.Core": "4.0.7", + "FubarCoder.RestSharp.Portable.HttpClient": "4.0.7", + "Newtonsoft.Json": "10.0.3", + "JsonSubTypes": "1.2.0" + }, + "frameworks": { + "{{targetFrameworkNuget}}": {} + } +} \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-471/travis.mustache b/src/main/resources/handlebars/csharp-471/travis.mustache new file mode 100644 index 0000000000..b26ecc6b13 --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/travis.mustache @@ -0,0 +1,9 @@ +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# +language: csharp +mono: + - latest +solution: {{{packageName}}}.sln +script: + - /bin/sh ./mono_nunit_test.sh diff --git a/src/main/resources/handlebars/csharp-471/visibility.mustache b/src/main/resources/handlebars/csharp-471/visibility.mustache new file mode 100644 index 0000000000..a1d1f4163d --- /dev/null +++ b/src/main/resources/handlebars/csharp-471/visibility.mustache @@ -0,0 +1 @@ +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp-dotnet2/csproj.mustache b/src/main/resources/handlebars/csharp-dotnet2/csproj.mustache index 035d83b2b5..93a03b7ba0 100644 --- a/src/main/resources/handlebars/csharp-dotnet2/csproj.mustache +++ b/src/main/resources/handlebars/csharp-dotnet2/csproj.mustache @@ -18,6 +18,6 @@ - + \ No newline at end of file diff --git a/src/main/resources/handlebars/csharp/Project.mustache b/src/main/resources/handlebars/csharp/Project.mustache index 4304147be1..d551f7d1a3 100644 --- a/src/main/resources/handlebars/csharp/Project.mustache +++ b/src/main/resources/handlebars/csharp/Project.mustache @@ -79,10 +79,10 @@ {{binRelativePath}}\JsonSubTypes.1.2.0\lib{{backslash}}{{targetFrameworkNuget}}\JsonSubTypes.dll - $(SolutionDir)\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - ..\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - ..\..\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - {{binRelativePath}}\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + $(SolutionDir)\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + ..\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + ..\..\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + {{binRelativePath}}\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll {{#generatePropertyChanged}} diff --git a/src/main/resources/handlebars/csharp/README.mustache b/src/main/resources/handlebars/csharp/README.mustache index c0770464ae..e7745565d8 100644 --- a/src/main/resources/handlebars/csharp/README.mustache +++ b/src/main/resources/handlebars/csharp/README.mustache @@ -42,7 +42,7 @@ This C# SDK is automatically generated by the [Swagger Codegen](https://github.c - Newtonsoft.Json >=10.0.3 {{/netStandard}} {{^netStandard}} -- [RestSharp](https://www.nuget.org/packages/RestSharp) - 110.2.0 or later +- [RestSharp](https://www.nuget.org/packages/RestSharp) - 105.1.0 or later - [Json.NET](https://www.nuget.org/packages/Newtonsoft.Json/) - 7.0.0 or later - [JsonSubTypes](https://www.nuget.org/packages/JsonSubTypes/) - 1.2.0 or later diff --git a/src/main/resources/handlebars/csharp/TestProject.mustache b/src/main/resources/handlebars/csharp/TestProject.mustache index 84a17d355b..ec7e18ba96 100644 --- a/src/main/resources/handlebars/csharp/TestProject.mustache +++ b/src/main/resources/handlebars/csharp/TestProject.mustache @@ -71,10 +71,10 @@ {{binRelativePath}}\JsonSubTypes.1.2.0\lib{{backslash}}{{targetFrameworkNuget}}\JsonSubTypes.dll - $(SolutionDir)\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - ..\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - ..\..\packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll - {{binRelativePath}}\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + $(SolutionDir)\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + ..\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + ..\..\packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll + {{binRelativePath}}\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll $(SolutionDir)\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/main/resources/handlebars/csharp/compile-mono.sh.mustache b/src/main/resources/handlebars/csharp/compile-mono.sh.mustache index 4b0198b7a3..c7188d022c 100644 --- a/src/main/resources/handlebars/csharp/compile-mono.sh.mustache +++ b/src/main/resources/handlebars/csharp/compile-mono.sh.mustache @@ -45,7 +45,7 @@ ${nuget_cmd} install src/{{packageName}}/packages.config -o packages; echo "[INFO] Copy DLLs to the 'bin' folder" mkdir -p bin; cp packages/Newtonsoft.Json.10.0.3/lib/{{targetFrameworkNuget}}/Newtonsoft.Json.dll bin/Newtonsoft.Json.dll; -cp packages/RestSharp.110.2.0/lib/{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}/RestSharp.dll bin/RestSharp.dll; +cp packages/RestSharp.105.1.0/lib/{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}/RestSharp.dll bin/RestSharp.dll; cp packages/JsonSubTypes.1.2.0/lib/{{targetFrameworkNuget}}/JsonSubTypes.dll bin/JsonSubTypes.dll {{#generatePropertyChanged}} cp packages/Fody.1.29.4/Fody.dll bin/Fody.dll diff --git a/src/main/resources/handlebars/csharp/compile.mustache b/src/main/resources/handlebars/csharp/compile.mustache index 16ca241b4f..73627a3b0d 100644 --- a/src/main/resources/handlebars/csharp/compile.mustache +++ b/src/main/resources/handlebars/csharp/compile.mustache @@ -17,7 +17,7 @@ if not exist ".\bin" mkdir bin copy packages\Newtonsoft.Json.10.0.3\lib{{backslash}}{{targetFrameworkNuget}}\Newtonsoft.Json.dll bin\Newtonsoft.Json.dll copy packages\JsonSubTypes.1.2.0\lib{{backslash}}{{targetFrameworkNuget}}\JsonSubTypes.dll bin\JsonSubTypes.dll -copy packages\RestSharp.110.2.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll bin\RestSharp.dll +copy packages\RestSharp.105.1.0\lib{{backslash}}{{#isNet40}}net4{{/isNet40}}{{^isNet40}}{{targetFrameworkNuget}}{{/isNet40}}\RestSharp.dll bin\RestSharp.dll {{#generatePropertyChanged}} copy packages\Fody.1.29.4\Fody.dll bin\Fody.dll copy packages\PropertyChanged.Fody.1.51.3\PropertyChanged.Fody.dll bin\PropertyChanged.Fody.dll diff --git a/src/main/resources/handlebars/csharp/netcore_project.mustache b/src/main/resources/handlebars/csharp/netcore_project.mustache index 83e7906825..4d0e27a7b9 100644 --- a/src/main/resources/handlebars/csharp/netcore_project.mustache +++ b/src/main/resources/handlebars/csharp/netcore_project.mustache @@ -23,7 +23,7 @@ {{/netStandard}} {{^netStandard}} - + {{/netStandard}} diff --git a/src/main/resources/handlebars/csharp/netcore_testproject.mustache b/src/main/resources/handlebars/csharp/netcore_testproject.mustache index 1c9a6533c6..7ed0a30d4d 100644 --- a/src/main/resources/handlebars/csharp/netcore_testproject.mustache +++ b/src/main/resources/handlebars/csharp/netcore_testproject.mustache @@ -22,7 +22,7 @@ {{/netStandard}} {{^netStandard}} - + {{/netStandard}} diff --git a/src/main/resources/handlebars/csharp/nuspec.mustache b/src/main/resources/handlebars/csharp/nuspec.mustache index ff574d1633..0585152685 100644 --- a/src/main/resources/handlebars/csharp/nuspec.mustache +++ b/src/main/resources/handlebars/csharp/nuspec.mustache @@ -32,7 +32,7 @@ - + {{#generatePropertyChanged}} diff --git a/src/main/resources/handlebars/csharp/packages.config.mustache b/src/main/resources/handlebars/csharp/packages.config.mustache index c8d3ba2780..57234ce284 100644 --- a/src/main/resources/handlebars/csharp/packages.config.mustache +++ b/src/main/resources/handlebars/csharp/packages.config.mustache @@ -1,6 +1,6 @@ - + {{#generatePropertyChanged}} diff --git a/src/main/resources/handlebars/csharp/packages_test.config.mustache b/src/main/resources/handlebars/csharp/packages_test.config.mustache index 0a41f16ac2..5e08ad3b67 100644 --- a/src/main/resources/handlebars/csharp/packages_test.config.mustache +++ b/src/main/resources/handlebars/csharp/packages_test.config.mustache @@ -1,7 +1,7 @@ - + diff --git a/src/test/java/io/swagger/codegen/v3/generators/java/CSharpGeneratorCodegenTest.java b/src/test/java/io/swagger/codegen/v3/generators/java/CSharpGeneratorCodegenTest.java new file mode 100644 index 0000000000..90d0dcb58f --- /dev/null +++ b/src/test/java/io/swagger/codegen/v3/generators/java/CSharpGeneratorCodegenTest.java @@ -0,0 +1,105 @@ +package io.swagger.codegen.v3.generators.java; + +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.codegen.v3.ClientOptInput; +import io.swagger.codegen.v3.CodegenArgument; +import io.swagger.codegen.v3.CodegenConstants; +import io.swagger.codegen.v3.DefaultGenerator; +import io.swagger.codegen.v3.config.CodegenConfigurator; +import io.swagger.codegen.v3.generators.AbstractCodegenTest; +import io.swagger.codegen.v3.service.GenerationRequest; +import io.swagger.codegen.v3.service.GeneratorService; +import io.swagger.codegen.v3.service.Options; +import io.swagger.util.Json; +import io.swagger.util.Yaml; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.rules.TemporaryFolder; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Collections; +import java.util.List; + +import static io.swagger.codegen.v3.generators.java.AbstractJavaCodegen.JAKARTA; +import static io.swagger.codegen.v3.generators.java.AbstractJavaCodegen.JAVA8_MODE; + +public class CSharpGeneratorCodegenTest extends AbstractCodegenTest { + @Test + public void testGenerator() throws Exception { + + String path = getOutFolder(false).getAbsolutePath(); + GenerationRequest request = new GenerationRequest(); + request + .codegenVersion(GenerationRequest.CodegenVersion.V3) // use V2 to target Swagger/OpenAPI 2.x Codegen version + .type(GenerationRequest.Type.CLIENT) + .lang("csharp") + .spec(loadSpecAsNode( "3_0_0/petstore-1.0.19.yaml", + true, // YAML file, use false for JSON + false)) // OpenAPI 3.x - use true for Swagger/OpenAPI 2.x definitions + .options( + new Options() + .addAdditionalProperty("targetFramework", "v4.5") + .outputDir(path) + ); + + List files = new GeneratorService().generationRequest(request).generate(); + Assert.assertFalse(files.isEmpty()); + for (File f: files) { + // test stuff + } + } + + protected static File getTmpFolder() { + try { + File outputFolder = Files.createTempFile("codegentest-", "-tmp").toFile(); + outputFolder.delete(); + outputFolder.mkdir(); + outputFolder.deleteOnExit(); + return outputFolder; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + protected static File getOutFolder(boolean delete) { + try { + File outputFolder = getTmpFolder(); + + System.out.println(outputFolder.getAbsolutePath()); + if (delete) { + // delete.. + } + return outputFolder; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + protected JsonNode loadSpecAsNode(final String file, boolean yaml, boolean v2) { + InputStream in = null; + String s = ""; + try { + in = getClass().getClassLoader().getResourceAsStream(file); + if (yaml) { + if (v2) { + return Yaml.mapper().readTree(in); + } else { + return io.swagger.v3.core.util.Yaml.mapper().readTree(in); + } + } + if (v2) { + return Json.mapper().readTree(in); + } + return io.swagger.v3.core.util.Json.mapper().readTree(in); + } catch (Exception e) { + throw new RuntimeException("could not load file " + file); + } finally { + IOUtils.closeQuietly(in); + } + } +} diff --git a/src/test/resources/3_0_0/petstore-1.0.19.yaml b/src/test/resources/3_0_0/petstore-1.0.19.yaml new file mode 100644 index 0000000000..9e9b4066d2 --- /dev/null +++ b/src/test/resources/3_0_0/petstore-1.0.19.yaml @@ -0,0 +1,803 @@ +openapi: 3.0.2 +info: + title: Swagger Petstore - OpenAPI 3.0 + description: |- + This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about + Swagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach! + You can now help us improve the API whether it's by making changes to the definition itself or to the code. + That way, with time, we can improve the API in general, and expose some of the new features in OAS3. + + Some useful links: + - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore) + - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) + termsOfService: http://swagger.io/terms/ + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.19 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: + - url: /api/v3 +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: http://swagger.io + - name: store + description: Access to Petstore orders + externalDocs: + description: Find out more about our store + url: http://swagger.io + - name: user + description: Operations about user +paths: + /pet: + put: + tags: + - pet + summary: Update an existing pet + description: Update an existing pet by Id + operationId: updatePet + requestBody: + description: Update an existent pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + "200": + description: Successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid ID supplied + "404": + description: Pet not found + "405": + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Add a new pet to the store + description: Add a new pet to the store + operationId: addPet + requestBody: + description: Create a new pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + "200": + description: Successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: false + explode: true + schema: + type: string + default: available + enum: + - available + - pending + - sold + responses: + "200": + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid status value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: false + explode: true + schema: + type: array + items: + type: string + responses: + "200": + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid tag value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}: + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: "" + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + - name: name + in: query + description: Name of pet that needs to be updated + schema: + type: string + - name: status + in: query + description: Status of pet that needs to be updated + schema: + type: string + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + delete: + tags: + - pet + summary: Deletes a pet + description: "" + operationId: deletePet + parameters: + - name: api_key + in: header + description: "" + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + "400": + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}/uploadImage: + post: + tags: + - pet + summary: uploads an image + description: "" + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + - name: additionalMetadata + in: query + description: Additional Metadata + required: false + schema: + type: string + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - write:pets + - read:pets + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + "200": + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: Place a new order in the store + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Order' + responses: + "200": + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + "405": + description: Invalid input + /store/order/{orderId}: + get: + tags: + - store + summary: Find purchase order by ID + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions. + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of order that needs to be fetched + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + "400": + description: Invalid ID supplied + "404": + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: integer + format: int64 + responses: + "400": + description: Invalid ID supplied + "404": + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + description: Created user object + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: Creates list of users with given input array + operationId: createUsersWithListInput + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + responses: + "200": + description: Successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + default: + description: successful operation + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: "" + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: false + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: false + schema: + type: string + responses: + "200": + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + "400": + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: "" + operationId: logoutUser + parameters: [] + responses: + default: + description: successful operation + /user/{username}: + get: + tags: + - user + summary: Get user by user name + description: "" + operationId: getUserByName + parameters: + - name: username + in: path + description: 'The name that needs to be fetched. Use user1 for testing. ' + required: true + schema: + type: string + responses: + "200": + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + "400": + description: Invalid username supplied + "404": + description: User not found + put: + tags: + - user + summary: Update user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that needs to be updated + required: true + schema: + type: string + requestBody: + description: Update an existent user in the store + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + "400": + description: Invalid username supplied + "404": + description: User not found +components: + schemas: + Order: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + petId: + type: integer + format: int64 + example: 198772 + quantity: + type: integer + format: int32 + example: 7 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + example: approved + enum: + - placed + - approved + - delivered + complete: + type: boolean + xml: + name: order + Customer: + type: object + properties: + id: + type: integer + format: int64 + example: 100000 + username: + type: string + example: fehguy + address: + type: array + xml: + name: addresses + wrapped: true + items: + $ref: '#/components/schemas/Address' + xml: + name: customer + Address: + type: object + properties: + street: + type: string + example: 437 Lytton + city: + type: string + example: Palo Alto + state: + type: string + example: CA + zip: + type: string + example: "94301" + xml: + name: address + Category: + type: object + properties: + id: + type: integer + format: int64 + example: 1 + name: + type: string + example: Dogs + xml: + name: category + User: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + username: + type: string + example: theUser + firstName: + type: string + example: John + lastName: + type: string + example: James + email: + type: string + example: john@email.com + password: + type: string + example: "12345" + phone: + type: string + example: "12345" + userStatus: + type: integer + description: User Status + format: int32 + example: 1 + xml: + name: user + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: tag + Pet: + required: + - name + - photoUrls + type: object + properties: + id: + type: integer + format: int64 + example: 10 + name: + type: string + example: doggie + category: + $ref: '#/components/schemas/Category' + photoUrls: + type: array + xml: + wrapped: true + items: + type: string + xml: + name: photoUrl + tags: + type: array + xml: + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: pet + ApiResponse: + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string + xml: + name: '##default' + requestBodies: + Pet: + description: Pet object that needs to be added to the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + UserArray: + description: List of user object + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://petstore3.swagger.io/oauth/authorize + scopes: + write:pets: modify pets in your account + read:pets: read your pets + api_key: + type: apiKey + name: api_key + in: header \ No newline at end of file