Skip to content

Commit ea559b5

Browse files
authored
[C#][NetCore] add multi-server support (#7433)
* multi server support in C# netcore clients * switch to IReadOnlyDictionary * minor fixes, add tests
1 parent 92f7a30 commit ea559b5

File tree

5 files changed

+466
-7
lines changed

5 files changed

+466
-7
lines changed

modules/openapi-generator/src/main/resources/csharp-netcore/Configuration.mustache

Lines changed: 133 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ namespace {{packageName}}.Client
4949
string.Format("Error calling {0}: {1}", methodName, response.RawContent),
5050
response.RawContent, response.Headers);
5151
}
52-
{{^netStandard}}if (status == 0)
52+
{{^netStandard}}
53+
if (status == 0)
5354
{
5455
return new ApiException(status,
5556
string.Format("Error calling {0}: {1}", methodName, response.ErrorText), response.ErrorText);
56-
}{{/netStandard}}
57+
}
58+
{{/netStandard}}
5759
return null;
5860
};
5961

@@ -82,6 +84,14 @@ namespace {{packageName}}.Client
8284

8385
private string _dateTimeFormat = ISO8601_DATETIME_FORMAT;
8486
private string _tempFolderPath = Path.GetTempPath();
87+
{{#servers.0}}
88+
89+
/// <summary>
90+
/// Gets or sets the servers defined in the OpenAPI spec.
91+
/// </summary>
92+
/// <value>The servers</value>
93+
private IList<IReadOnlyDictionary<string, object>> _servers;
94+
{{/servers.0}}
8595

8696
/// <summary>
8797
/// HTTPSigning configuration
@@ -102,6 +112,48 @@ namespace {{packageName}}.Client
102112
DefaultHeaders = new {{^net35}}Concurrent{{/net35}}Dictionary<string, string>();
103113
ApiKey = new {{^net35}}Concurrent{{/net35}}Dictionary<string, string>();
104114
ApiKeyPrefix = new {{^net35}}Concurrent{{/net35}}Dictionary<string, string>();
115+
{{#servers}}
116+
{{#-first}}
117+
Servers = new List<IReadOnlyDictionary<string, object>>()
118+
{
119+
{{/-first}}
120+
{
121+
new Dictionary<string, object> {
122+
{"url", "{{{url}}}"},
123+
{"description", "{{{description}}}{{^description}}No description provided{{/description}}"},
124+
{{#variables}}
125+
{{#-first}}
126+
{
127+
"variables", new Dictionary<string, object> {
128+
{{/-first}}
129+
{
130+
"{{{name}}}", new Dictionary<string, object> {
131+
{"description", "{{{description}}}{{^description}}No description provided{{/description}}"},
132+
{"default_value", "{{{defaultValue}}}"},
133+
{{#enumValues}}
134+
{{#-first}}
135+
{
136+
"enum_values", new List<string>() {
137+
{{/-first}}
138+
"{{{.}}}"{{^-last}},{{/-last}}
139+
{{#-last}}
140+
}
141+
}
142+
{{/-last}}
143+
{{/enumValues}}
144+
}
145+
}{{^-last}},{{/-last}}
146+
{{#-last}}
147+
}
148+
}
149+
{{/-last}}
150+
{{/variables}}
151+
}
152+
}{{^-last}},{{/-last}}
153+
{{#-last}}
154+
};
155+
{{/-last}}
156+
{{/servers}}
105157

106158
// Setting Timeout has side effects (forces ApiClient creation).
107159
Timeout = 100000;
@@ -337,6 +389,84 @@ namespace {{packageName}}.Client
337389
_apiKey = value;
338390
}
339391
}
392+
{{#servers.0}}
393+
394+
/// <summary>
395+
/// Gets or sets the servers.
396+
/// </summary>
397+
/// <value>The servers.</value>
398+
public virtual IList<IReadOnlyDictionary<string, object>> Servers
399+
{
400+
get { return _servers; }
401+
set
402+
{
403+
if (value == null)
404+
{
405+
throw new InvalidOperationException("Servers may not be null.");
406+
}
407+
_servers = value;
408+
}
409+
}
410+
411+
/// <summary>
412+
/// Returns URL based on server settings without providing values
413+
/// for the variables
414+
/// </summary>
415+
/// <param name="index">Array index of the server settings.</param>
416+
/// <return>The server URL.</return>
417+
public string GetServerUrl(int index)
418+
{
419+
return GetServerUrl(index, null);
420+
}
421+
422+
/// <summary>
423+
/// Returns URL based on server settings.
424+
/// </summary>
425+
/// <param name="index">Array index of the server settings.</param>
426+
/// <param name="inputVariables">Dictionary of the variables and the corresponding values.</param>
427+
/// <return>The server URL.</return>
428+
public string GetServerUrl(int index, Dictionary<string, string> inputVariables)
429+
{
430+
if (index < 0 || index >= Servers.Count)
431+
{
432+
throw new InvalidOperationException($"Invalid index {index} when selecting the server. Must be less than {Servers.Count}.");
433+
}
434+
435+
if (inputVariables == null)
436+
{
437+
inputVariables = new Dictionary<string, string>();
438+
}
439+
440+
IReadOnlyDictionary<string, object> server = Servers[index];
441+
string url = (string)server["url"];
442+
443+
// go through variable and assign a value
444+
foreach (KeyValuePair<string, object> variable in (IReadOnlyDictionary<string, object>)server["variables"])
445+
{
446+
447+
IReadOnlyDictionary<string, object> serverVariables = (IReadOnlyDictionary<string, object>)(variable.Value);
448+
449+
if (inputVariables.ContainsKey(variable.Key))
450+
{
451+
if (((List<string>)serverVariables["enum_values"]).Contains(inputVariables[variable.Key]))
452+
{
453+
url = url.Replace("{" + variable.Key + "}", inputVariables[variable.Key]);
454+
}
455+
else
456+
{
457+
throw new InvalidOperationException($"The variable `{variable.Key}` in the server URL has invalid value #{inputVariables[variable.Key]}. Must be {(List<string>)serverVariables["enum_values"]}");
458+
}
459+
}
460+
else
461+
{
462+
// use defualt value
463+
url = url.Replace("{" + variable.Key + "}", (string)serverVariables["default_value"]);
464+
}
465+
}
466+
467+
return url;
468+
}
469+
{{/servers.0}}
340470

341471
/// <summary>
342472
/// Gets and Sets the HTTPSigningConfiuration
@@ -431,4 +561,4 @@ namespace {{packageName}}.Client
431561
}
432562
#endregion Static Members
433563
}
434-
}
564+
}

samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/Api/PetApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
namespace Org.OpenAPITools.Test
2525
{
2626
/// <summary>
27-
/// Class for testing PetApi
27+
/// Class for testing PetApi
2828
/// </summary>
2929
/// <remarks>
3030
/// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.IO;
3+
using System.Collections.Generic;
4+
using System.Collections.ObjectModel;
5+
using System.Linq;
6+
using System.Reflection;
7+
using RestSharp;
8+
using Xunit;
9+
10+
using Org.OpenAPITools.Client;
11+
using Org.OpenAPITools.Api;
12+
using Org.OpenAPITools.Model;
13+
14+
namespace Org.OpenAPITools.Test
15+
{
16+
/// <summary>
17+
/// Class for testing Configuration
18+
/// </summary>
19+
public class ConfigurationTests
20+
{
21+
public ConfigurationTests()
22+
{
23+
}
24+
25+
/// <summary>
26+
/// Test GetServerUrl
27+
/// </summary>
28+
[Fact]
29+
public void GetServerUrlTest()
30+
{
31+
Configuration c = new Configuration();
32+
// no variable (null) provided
33+
Assert.Equal("https://localhost:8080/v2", c.GetServerUrl(1, null));
34+
// no variable (empty dictionary) provided
35+
Assert.Equal("https://localhost:8080/v2", c.GetServerUrl(1, new Dictionary<string, string>()));
36+
37+
Assert.Equal("https://localhost:8080/v1", c.GetServerUrl(1, new Dictionary<string, string>() { { "version", "v1" } }));
38+
39+
Assert.Throws<InvalidOperationException>(() => c.GetServerUrl(1, new Dictionary<string, string>() { { "version", "v3" } }));
40+
41+
// test the first server (index 0)
42+
Assert.Equal("http://petstore.swagger.io:80/v2", c.GetServerUrl(0));
43+
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)