Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[csharp-netcore] Adding generic host library #10627

Merged
merged 47 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d71105a
Merge pull request #1 from OpenAPITools/master
devhl-labs Jun 2, 2021
36c514b
Merge pull request #2 from OpenAPITools/master
devhl-labs Jun 8, 2021
a0c6107
Merge branch 'OpenAPITools:master' into master
devhl-labs Jun 12, 2021
ece89e5
Merge branch 'OpenAPITools:master' into master
devhl-labs Jul 3, 2021
d2a46f6
Merge branch 'OpenAPITools:master' into master
devhl-labs Jul 5, 2021
3ca0921
Merge branch 'OpenAPITools:master' into master
devhl-labs Jul 15, 2021
c2a1a4c
Merge branch 'OpenAPITools:master' into master
devhl-labs Aug 3, 2021
3456183
Merge branch 'OpenAPITools:master' into master
devhl-labs Oct 15, 2021
7dfcdee
added generichost library
devhl-labs Oct 18, 2021
2a1c275
added templates
devhl-labs Oct 18, 2021
9a21519
added an event, improved docs, added logging
devhl-labs Oct 23, 2021
39af198
adding event args file
devhl-labs Oct 23, 2021
a4a1d4e
fixed hard coded package name
devhl-labs Oct 23, 2021
63f2915
added an AddTokens overload for a single token
devhl-labs Oct 23, 2021
a83fc74
changed api clients to singletons to support the event registration
devhl-labs Oct 23, 2021
f786322
Merge branch 'OpenAPITools:master' into master
devhl-labs Nov 7, 2021
28cdd4c
Merge branch 'master' into generic-host
devhl-labs Nov 7, 2021
2b5d5a6
build samples
devhl-labs Nov 7, 2021
4ea5722
log exceptions while executing api responded event
devhl-labs Nov 24, 2021
1f2937e
nrt bug fixes, dangling comma fix
devhl-labs Nov 24, 2021
fafe671
resolving comments
devhl-labs Nov 25, 2021
c7f6fe6
removed debugging lines
devhl-labs Nov 25, 2021
77ea9e8
refactored token provider
devhl-labs Dec 4, 2021
641a7b9
rate limit provider now default
devhl-labs Dec 4, 2021
b909944
updated readme, added ConfigureAwait(false)
devhl-labs Dec 19, 2021
e069979
DI fixes
devhl-labs Dec 21, 2021
deba536
removed a hard coded project name
devhl-labs Dec 21, 2021
b695cf7
fixed nrt bugs
devhl-labs Dec 21, 2021
0c1c382
improved NRT and .net 3.1 support
devhl-labs Dec 28, 2021
63a3950
renamed projectName to apiName, added cli option
devhl-labs Dec 29, 2021
6514b77
trying to avoid conflict
devhl-labs Dec 29, 2021
4e90817
set GenerateAssemlbyInfo to true
devhl-labs Dec 31, 2021
190a3aa
created docs/scripts folder
devhl-labs Dec 31, 2021
fb3f3f5
moved ApiTestsBase.cs to not get overwritten
devhl-labs Dec 31, 2021
a3a9a30
test fixes and improvements
devhl-labs Dec 31, 2021
4133334
fixed licenseId bug, updated readme
devhl-labs Dec 31, 2021
31f9629
Merge branch 'OpenAPITools:master' into master
devhl-labs Jan 3, 2022
cacf3dc
Merge branch 'master' into generic-host
devhl-labs Jan 3, 2022
c87c202
build samples
devhl-labs Jan 3, 2022
62c5b99
export docs
devhl-labs Jan 3, 2022
b106cf4
removed new language features
devhl-labs Jan 6, 2022
b45f066
added support for .net standard 2.0
devhl-labs Jan 8, 2022
44f5955
added git_push.ps1
devhl-labs Jan 22, 2022
6250bb8
fixed bug in git_push.sh due to the new directory, prompting user for…
devhl-labs Jan 23, 2022
ad8d093
moved documentation folders
devhl-labs Jan 23, 2022
fa7b202
fixed bug when apiKey in query
devhl-labs Jan 25, 2022
0f6d741
bug fix
devhl-labs Jan 26, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/generators/csharp-netcore.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
|apiName|Must be a valid C# class name. Only used in Generic Host library. Default: Api| |Api|
|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive| |false|
|conditionalSerialization|Serialize only those properties which are initialized by user, accepted values are true or false, default value is false.| |false|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|interfacePrefix|Prefix interfaces with a community standard or widely accepted prefix.| |I|
|library|HTTP library template (sub-template) to use|<dl><dt>**httpclient**</dt><dd>HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. May subject to breaking changes without further notice.)</dd><dt>**restsharp**</dt><dd>RestSharp (https://github.com/restsharp/RestSharp)</dd></dl>|restsharp|
|library|HTTP library template (sub-template) to use|<dl><dt>**generichost**</dt><dd>HttpClient with Generic Host dependency injection (https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host) (Experimental. Subject to breaking changes without notice.)</dd><dt>**httpclient**</dt><dd>HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. Subject to breaking changes without notice.)</dd><dt>**restsharp**</dt><dd>RestSharp (https://github.com/restsharp/RestSharp)</dd></dl>|restsharp|
|licenseId|The identifier of the license| |null|
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |PascalCase|
|netCoreProjectFile|Use the new format (.NET Core) for .NET project files (.csproj).| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class CodegenConstants {
public static final String SKIP_FORM_MODEL = "skipFormModel";
/* /end System Properties */

public static final String API_NAME = "apiName";

public static final String API_PACKAGE = "apiPackage";
public static final String API_PACKAGE_DESC = "package for generated api classes";

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ Name | Type | Description | Notes
{{/responses}}
{{/responses.0}}

[[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)
[[Back to top]](#) [[Back to API list]](../{{#useGenericHost}}../{{/useGenericHost}}README.md#documentation-for-api-endpoints) [[Back to Model list]](../{{#useGenericHost}}../{{/useGenericHost}}README.md#documentation-for-models) [[Back to README]](../{{#useGenericHost}}../{{/useGenericHost}}README.md)

{{/operation}}
{{/operations}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <auto-generated>
{{>partial_header}}
{{#nullableReferenceTypes}}#nullable enable{{/nullableReferenceTypes}}

using System;

namespace {{packageName}}.Client
{
/// <summary>
/// API Exception
/// </summary>
{{>visibility}} class ApiException : Exception
{
/// <summary>
/// The reason the api request failed
/// </summary>
public string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} ReasonPhrase { get; }

/// <summary>
/// The HttpStatusCode
/// </summary>
public System.Net.HttpStatusCode StatusCode { get; }

/// <summary>
/// The raw data returned by the api
/// </summary>
public string RawContent { get; }

/// <summary>
/// Construct the ApiException from parts of the reponse
/// </summary>
/// <param name="reasonPhrase"></param>
/// <param name="statusCode"></param>
/// <param name="rawContent"></param>
public ApiException(string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} reasonPhrase, System.Net.HttpStatusCode statusCode, string rawContent) : base(reasonPhrase ?? rawContent)
{
ReasonPhrase = reasonPhrase;

StatusCode = statusCode;

RawContent = rawContent;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// <auto-generated>
{{partial_header}}
{{#nullableReferenceTypes}}#nullable enable{{/nullableReferenceTypes}}

using System;

namespace {{packageName}}.Client
{
/// <summary>
/// A token constructed from an apiKey.
/// </summary>
public class ApiKeyToken : TokenBase
{
private string _raw;

/// <summary>
/// Constructs an ApiKeyToken object.
/// </summary>
/// <param name="value"></param>
/// <param name="prefix"></param>
/// <param name="timeout"></param>
public ApiKeyToken(string value, string prefix = "Bearer ", TimeSpan? timeout = null) : base(timeout)
{
_raw = $"{ prefix }{ value }";
}

/// <summary>
/// Places the token in the cookie.
/// </summary>
/// <param name="request"></param>
/// <param name="cookieName"></param>
public virtual void UseInCookie(System.Net.Http.HttpRequestMessage request, string cookieName)
{
request.Headers.Add("Cookie", $"{ cookieName }=_raw");
}

/// <summary>
/// Places the token in the header.
/// </summary>
/// <param name="request"></param>
/// <param name="headerName"></param>
public virtual void UseInHeader(System.Net.Http.HttpRequestMessage request, string headerName)
{
request.Headers.Add(headerName, _raw);
}

/// <summary>
/// Places the token in the query.
/// </summary>
/// <param name="request"></param>
/// <param name="uriBuilder"></param>
/// <param name="parseQueryString"></param>
/// <param name="parameterName"></param>
public virtual void UseInQuery(System.Net.Http.HttpRequestMessage request, UriBuilder uriBuilder, System.Collections.Specialized.NameValueCollection parseQueryString, string parameterName)
{
parseQueryString[parameterName] = Uri.EscapeDataString(_raw).ToString(){{#nullableReferenceTypes}}!{{/nullableReferenceTypes}};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Net;

namespace {{packageName}}.Client
{
/// <summary>
/// Useful for tracking server health.
/// </summary>
public class ApiResponseEventArgs : EventArgs
{
/// <summary>
/// The time the request was sent.
/// </summary>
public DateTime RequestedAt { get; }
/// <summary>
/// The time the response was received.
/// </summary>
public DateTime ReceivedAt { get; }
/// <summary>
/// The HttpStatusCode received.
/// </summary>
public HttpStatusCode HttpStatus { get; }
/// <summary>
/// The path requested.
/// </summary>
public string Path { get; }
/// <summary>
/// The elapsed time from request to response.
/// </summary>
public TimeSpan ToTimeSpan => this.ReceivedAt - this.RequestedAt;

/// <summary>
/// The event args used to track server health.
/// </summary>
/// <param name="requestedAt"></param>
/// <param name="receivedAt"></param>
/// <param name="httpStatus"></param>
/// <param name="path"></param>
public ApiResponseEventArgs(DateTime requestedAt, DateTime receivedAt, HttpStatusCode httpStatus, string path)
{
RequestedAt = requestedAt;
ReceivedAt = receivedAt;
HttpStatus = httpStatus;
Path = path;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// <auto-generated>
{{>partial_header}}
{{#nullableReferenceTypes}}#nullable enable{{/nullableReferenceTypes}}

using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;

namespace {{packageName}}.Client
{
/// <summary>
/// Provides a non-generic contract for the ApiResponse wrapper.
/// </summary>
public interface IApiResponse
{
/// <summary>
/// The data type of <see cref="Data"/>
/// </summary>
Type ResponseType { get; }

/// <summary>
/// Gets or sets the status code (HTTP status code)
/// </summary>
/// <value>The status code.</value>
HttpStatusCode StatusCode { get; }

/// <summary>
/// The raw content of this response
/// </summary>
string RawContent { get; }
}

/// <summary>
/// API Response
/// </summary>
{{>visibility}} partial class ApiResponse<T> : IApiResponse
{
#region Properties

/// <summary>
/// The deserialized content
/// </summary>
{{! .net 3.1 does not support unconstrained nullable T }}
public T{{#nullableReferenceTypes}}{{^netcoreapp3.1}}?{{/netcoreapp3.1}}{{/nullableReferenceTypes}} Content { get; set; }

/// <summary>
/// Gets or sets the status code (HTTP status code)
/// </summary>
/// <value>The status code.</value>
public HttpStatusCode StatusCode { get; }

/// <summary>
/// The content of this response
/// </summary>
public Type ResponseType
{
get { return typeof(T); }
}

/// <summary>
/// The raw data
/// </summary>
public string RawContent { get; }

/// <summary>
/// The IsSuccessStatusCode from the api response
/// </summary>
public bool IsSuccessStatusCode { get; }

/// <summary>
/// The reason phrase contained in the api response
/// </summary>
public string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} ReasonPhrase { get; }

/// <summary>
/// The headers contained in the api response
/// </summary>
public System.Net.Http.Headers.HttpResponseHeaders Headers { get; }

#endregion Properties

/// <summary>
/// Construct the reponse using an HttpResponseMessage
/// </summary>
/// <param name="response"></param>
/// <param name="rawContent"></param>
public ApiResponse(System.Net.Http.HttpResponseMessage response, string rawContent)
{
StatusCode = response.StatusCode;
Headers = response.Headers;
IsSuccessStatusCode = response.IsSuccessStatusCode;
ReasonPhrase = response.ReasonPhrase;
RawContent = rawContent;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{{>partial_header}}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using Microsoft.Extensions.Hosting;
using {{packageName}}.Client;{{#hasImport}}
using {{packageName}}.{{modelPackage}};{{/hasImport}}


{{{testInstructions}}}


namespace {{packageName}}.Test.Api
{
/// <summary>
/// Base class for API tests
/// </summary>
public class ApiTestsBase
{
protected readonly IHost _host;

public ApiTestsBase(string[] args)
{
_host = CreateHostBuilder(args).Build();
}

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.Configure{{apiName}}((context, options) =>
{
{{#hasApiKeyMethods}}ApiKeyToken apiKeyToken = new ApiKeyToken(context.Configuration["<token>"], timeout: TimeSpan.FromSeconds(1));
options.AddTokens(apiKeyToken);
{{/hasApiKeyMethods}}{{#hasHttpBearerMethods}}
BearerToken bearerToken = new BearerToken(context.Configuration["<token>"], timeout: TimeSpan.FromSeconds(1));
options.AddTokens(bearerToken);
{{/hasHttpBearerMethods}}{{#hasHttpBasicMethods}}
BasicToken basicToken = new BasicToken(context.Configuration["<username>"], context.Configuration["<password>"], timeout: TimeSpan.FromSeconds(1));
options.AddTokens(basicToken);
{{/hasHttpBasicMethods}}{{#hasHttpSignatureMethods}}
HttpSigningConfiguration config = new HttpSigningConfiguration("<keyId>", "<keyFilePath>", null, new List<string>(), HashAlgorithmName.SHA256, "<signingAlgorithm>", 0);
HttpSignatureToken httpSignatureToken = new HttpSignatureToken(config, timeout: TimeSpan.FromSeconds(1));
options.AddTokens(httpSignatureToken);
{{/hasHttpSignatureMethods}}{{#hasOAuthMethods}}
OAuthToken oauthToken = new OAuthToken(context.Configuration["<token>"], timeout: TimeSpan.FromSeconds(1));
options.AddTokens(oauthToken);{{/hasOAuthMethods}}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <auto-generated>
{{partial_header}}
{{#nullableReferenceTypes}}#nullable enable{{/nullableReferenceTypes}}

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace {{packageName}}.Client
{
/// <summary>
/// A token constructed from a username and password.
/// </summary>
public class BasicToken : TokenBase
{
private string _username;

private string _password;

/// <summary>
/// Constructs a BasicToken object.
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <param name="timeout"></param>
public BasicToken(string username, string password, TimeSpan? timeout = null) : base(timeout)
{
_username = username;

_password = password;
}

/// <summary>
/// Places the token in the header.
/// </summary>
/// <param name="request"></param>
/// <param name="headerName"></param>
public virtual void UseInHeader(System.Net.Http.HttpRequestMessage request, string headerName)
{
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", {{packageName}}.Client.ClientUtils.Base64Encode(_username + ":" + _password));
}
}
}
Loading