Skip to content

Commit 8cc39c8

Browse files
committed
Fixed issue with nullable AllowedString values
1 parent 9270993 commit 8cc39c8

File tree

6 files changed

+245
-12
lines changed

6 files changed

+245
-12
lines changed

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
publish:
77
env:
88
SOLUTION: 'GoLive.Generator.ApiClientGenerator/GoLive.Generator.ApiClientGenerator.csproj'
9-
BUILD_VER: '3.1'
9+
BUILD_VER: '3.2'
1010
name: build, pack & publish
1111
runs-on: windows-latest
1212
steps:

GoLive.Generator.ApiClientGenerator.Tests.WebApi/Controllers/NonApiController.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading.Tasks;
1+
using System.ComponentModel.DataAnnotations;
2+
using System.Threading.Tasks;
23
using Microsoft.AspNetCore.Mvc;
34

45
namespace GoLive.Generator.ApiClientGenerator.Tests.WebApi.Controllers;
@@ -16,4 +17,17 @@ public async Task<ActionResult> TestModelBinderDifferentNameUnderId3([CustomAttr
1617
{
1718
return Ok();
1819
}
20+
21+
[HttpGet]
22+
public async Task<ActionResult> TestWithAllowedValues(string Id, [AllowedValues("start", "stop", "kill", "restart")]string DesiredState)
23+
{
24+
return Ok();
25+
}
26+
27+
28+
[HttpGet]
29+
public async Task<ActionResult> TestWithAllowedValuesButNullable(string Id, [AllowedValues("start", "stop", "kill", "restart")]string? DesiredState)
30+
{
31+
return Ok();
32+
}
1933
}

GoLive.Generator.ApiClientGenerator.Tests.WebApi/GeneratedApiClient.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,70 @@ public string TestModelBinderDifferentNameUnderId3_Url(System.String Id, QuerySt
554554
{
555555
return $"/api/NonApi/TestModelBinderDifferentNameUnderId3/{Id}{queryString}";
556556
}
557+
558+
public readonly struct TestWithAllowedValues_DesiredState
559+
{
560+
private TestWithAllowedValues_DesiredState(string value)
561+
{
562+
Value = value;
563+
}
564+
565+
public string Value { get; }
566+
567+
public override string ToString() => $"{Value}";
568+
public static TestWithAllowedValues_DesiredState start = new TestWithAllowedValues_DesiredState("start");
569+
public static TestWithAllowedValues_DesiredState stop = new TestWithAllowedValues_DesiredState("stop");
570+
public static TestWithAllowedValues_DesiredState kill = new TestWithAllowedValues_DesiredState("kill");
571+
public static TestWithAllowedValues_DesiredState restart = new TestWithAllowedValues_DesiredState("restart");
572+
}
573+
574+
public async Task<Response> TestWithAllowedValues(string Id, TestWithAllowedValues_DesiredState? DesiredState = default, QueryString queryString = default, CancellationToken _token = default)
575+
{
576+
queryString = queryString.Add("DesiredState", DesiredState.Value.ToString());
577+
using var request = new HttpRequestMessage(HttpMethod.Get, $"/api/NonApi/TestWithAllowedValues/{Id}{queryString}");
578+
using var result = await _client.SendAsync(request, _token);
579+
return new Response(result.StatusCode, result.Headers);
580+
}
581+
582+
public string TestWithAllowedValues_Url(string Id, string DesiredState = default, QueryString queryString = default)
583+
{
584+
queryString = queryString.Add("DesiredState", DesiredState.ToString());
585+
return $"/api/NonApi/TestWithAllowedValues/{Id}{queryString}";
586+
}
587+
588+
public readonly struct TestWithAllowedValuesButNullable_DesiredState
589+
{
590+
private TestWithAllowedValuesButNullable_DesiredState(string value)
591+
{
592+
Value = value;
593+
}
594+
595+
public string Value { get; }
596+
597+
public override string ToString() => $"{Value}";
598+
public static TestWithAllowedValuesButNullable_DesiredState start = new TestWithAllowedValuesButNullable_DesiredState("start");
599+
public static TestWithAllowedValuesButNullable_DesiredState stop = new TestWithAllowedValuesButNullable_DesiredState("stop");
600+
public static TestWithAllowedValuesButNullable_DesiredState kill = new TestWithAllowedValuesButNullable_DesiredState("kill");
601+
public static TestWithAllowedValuesButNullable_DesiredState restart = new TestWithAllowedValuesButNullable_DesiredState("restart");
602+
}
603+
604+
public async Task<Response> TestWithAllowedValuesButNullable(string Id, TestWithAllowedValuesButNullable_DesiredState? DesiredState = default, QueryString queryString = default, CancellationToken _token = default)
605+
{
606+
if (DesiredState.HasValue)
607+
{
608+
queryString = queryString.Add("DesiredState", DesiredState.Value.ToString());
609+
}
610+
611+
using var request = new HttpRequestMessage(HttpMethod.Get, $"/api/NonApi/TestWithAllowedValuesButNullable/{Id}{queryString}");
612+
using var result = await _client.SendAsync(request, _token);
613+
return new Response(result.StatusCode, result.Headers);
614+
}
615+
616+
public string TestWithAllowedValuesButNullable_Url(string Id, string DesiredState = default, QueryString queryString = default)
617+
{
618+
queryString = queryString.Add("DesiredState", DesiredState.ToString());
619+
return $"/api/NonApi/TestWithAllowedValuesButNullable/{Id}{queryString}";
620+
}
557621
}
558622

559623
public class TestIssueClient

GoLive.Generator.ApiClientGenerator.Tests.WebApi/GeneratedApiClient.json

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,112 @@
667667
"AllAttributes": [
668668
"Microsoft.AspNetCore.Mvc.HttpGetAttribute"
669669
]
670+
},
671+
{
672+
"Name": "TestWithAllowedValues",
673+
"FullMethodName": "GoLive.Generator.ApiClientGenerator.Tests.WebApi.Controllers.NonApiController.TestWithAllowedValues",
674+
"Method": {
675+
"Method": "GET"
676+
},
677+
"Route": "",
678+
"RouteSetByAttributes": false,
679+
"ReturnTypeName": null,
680+
"ReturnTypeStruct": true,
681+
"HasCustomFormatter": false,
682+
"Mapping": [
683+
{
684+
"Key": "Id",
685+
"Parameter": {
686+
"FullTypeName": "string",
687+
"GenericTypeName": null,
688+
"HasDefaultValue": false,
689+
"DefaultValue": null,
690+
"Nullable": false,
691+
"Attributes": [],
692+
"SpecialType": 20,
693+
"AllowedStringValues": null
694+
}
695+
},
696+
{
697+
"Key": "DesiredState",
698+
"Parameter": {
699+
"FullTypeName": "string",
700+
"GenericTypeName": null,
701+
"HasDefaultValue": false,
702+
"DefaultValue": null,
703+
"Nullable": false,
704+
"Attributes": [
705+
"System.ComponentModel.DataAnnotations.AllowedValuesAttribute"
706+
],
707+
"SpecialType": 20,
708+
"AllowedStringValues": [
709+
"start",
710+
"stop",
711+
"kill",
712+
"restart"
713+
]
714+
}
715+
}
716+
],
717+
"Body": [],
718+
"XmlComments": "",
719+
"CalculatedURL": "/api/NonApi/TestWithAllowedValues/{Id}",
720+
"AllAttributes": [
721+
"Microsoft.AspNetCore.Mvc.HttpGetAttribute"
722+
]
723+
},
724+
{
725+
"Name": "TestWithAllowedValuesButNullable",
726+
"FullMethodName": "GoLive.Generator.ApiClientGenerator.Tests.WebApi.Controllers.NonApiController.TestWithAllowedValuesButNullable",
727+
"Method": {
728+
"Method": "GET"
729+
},
730+
"Route": "",
731+
"RouteSetByAttributes": false,
732+
"ReturnTypeName": null,
733+
"ReturnTypeStruct": true,
734+
"HasCustomFormatter": false,
735+
"Mapping": [
736+
{
737+
"Key": "Id",
738+
"Parameter": {
739+
"FullTypeName": "string",
740+
"GenericTypeName": null,
741+
"HasDefaultValue": false,
742+
"DefaultValue": null,
743+
"Nullable": false,
744+
"Attributes": [],
745+
"SpecialType": 20,
746+
"AllowedStringValues": null
747+
}
748+
},
749+
{
750+
"Key": "DesiredState",
751+
"Parameter": {
752+
"FullTypeName": "string",
753+
"GenericTypeName": null,
754+
"HasDefaultValue": false,
755+
"DefaultValue": null,
756+
"Nullable": true,
757+
"Attributes": [
758+
"System.ComponentModel.DataAnnotations.AllowedValuesAttribute"
759+
],
760+
"SpecialType": 20,
761+
"AllowedStringValues": [
762+
"start",
763+
"stop",
764+
"kill",
765+
"restart"
766+
]
767+
}
768+
}
769+
],
770+
"Body": [],
771+
"XmlComments": "",
772+
"CalculatedURL": "/api/NonApi/TestWithAllowedValuesButNullable/{Id}",
773+
"AllAttributes": [
774+
"Microsoft.AspNetCore.Mvc.HttpGetAttribute"
775+
]
670776
}
671777
],
672778
"XmlComments": "",

GoLive.Generator.ApiClientGenerator.Tests.WebApi/GeneratedURLs.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ public static string NonApi_TestModelBinderDifferentNameUnderId3(System.String I
9595
return $"/api/NonApi/TestModelBinderDifferentNameUnderId3/{Id}{queryString}";
9696
}
9797

98+
public static string NonApi_TestWithAllowedValues(string Id, string DesiredState = default, QueryString queryString = default)
99+
{
100+
queryString = queryString.Add("DesiredState", DesiredState.ToString());
101+
return $"/api/NonApi/TestWithAllowedValues/{Id}{queryString}";
102+
}
103+
104+
public static string NonApi_TestWithAllowedValuesButNullable(string Id, string DesiredState = default, QueryString queryString = default)
105+
{
106+
queryString = queryString.Add("DesiredState", DesiredState.ToString());
107+
return $"/api/NonApi/TestWithAllowedValuesButNullable/{Id}{queryString}";
108+
}
109+
98110
public static string TestIssue_Get(string Id = "", QueryString queryString = default)
99111
{
100112
return $"/api/TestIssue/Get/{Id}{queryString}";

GoLive.Generator.ApiClientGenerator/ApiClientGenerator.cs

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,22 @@ private static void SetUpSingleApi(RouteGeneratorSettings config, ControllerRout
383383
{
384384
if (m.Parameter.AllowedStringValues is { Length: > 0 })
385385
{
386-
return $"{action.Name}_{m.Key}{(m.Parameter.HasDefaultValue ? "?" : "")} {m.Key} {GetDefaultValue(m.Parameter)}";
386+
StringBuilder retr = new StringBuilder();
387+
retr.Append($"{action.Name}_{m.Key}");
388+
389+
if (m.Parameter.Nullable)
390+
{
391+
retr.Append("?");
392+
}
393+
else
394+
{
395+
retr.Append($"{(!m.Parameter.HasDefaultValue ? "?" : "")} ");
396+
}
397+
398+
retr.Append($"{m.Key} ");
399+
retr.Append($"{GetDefaultValue(m.Parameter)}");
400+
401+
return retr.ToString();
387402
}
388403

389404
return $"{m.Parameter.FullTypeName} {m.Key} {GetDefaultValue(m.Parameter)}";
@@ -535,30 +550,52 @@ private static void SetUpSingleApi(RouteGeneratorSettings config, ControllerRout
535550
&& !actionValues.ContainsKey(f.Key) && !urlTemplate.Segments.Any(r => string.Equals(r.Parameter, f.Key, StringComparison.InvariantCultureIgnoreCase)
536551
&& r.Restriction == URLTemplateSegmentKnownRestrictions.Optional)))
537552
{
553+
bool skipCreatingBracket = false;
538554
if (parameterMapping.Parameter.SpecialType == SpecialType.System_String && parameterMapping.Parameter.AllowedStringValues is null or { Length: 0 })
539555
{
540556
source.AppendLine($"if (!string.IsNullOrWhiteSpace({parameterMapping.Key}))");
541557
}
542-
else if (parameterMapping.Parameter.SpecialType == SpecialType.System_String && parameterMapping.Parameter.AllowedStringValues is { Length: > 0 })
558+
else if (parameterMapping.Parameter.SpecialType == SpecialType.System_String && parameterMapping.Parameter.AllowedStringValues is { Length: > 0 } )
543559
{
544-
source.AppendLine($"if ({parameterMapping.Key}.HasValue)");
560+
if (parameterMapping.Parameter.Nullable)
561+
{
562+
source.AppendLine($"if ({parameterMapping.Key}.HasValue)");
563+
}
564+
else
565+
{
566+
skipCreatingBracket = true;
567+
}
568+
545569
}
546570
else
547571
{
548572
source.AppendLine($"if ({parameterMapping.Key} != default)");
549573
}
550574

551-
using (source.CreateBracket())
575+
if (!skipCreatingBracket)
552576
{
553-
if (parameterMapping.Parameter.SpecialType == SpecialType.System_String && parameterMapping.Parameter.AllowedStringValues is { Length: > 0 })
554-
{
555-
source.AppendLine($"queryString = queryString.Add(\"{parameterMapping.Key}\", {parameterMapping.Key}.Value.ToString());");
556-
}
557-
else
577+
using (source.CreateBracket())
558578
{
559-
source.AppendLine($"queryString = queryString.Add(\"{parameterMapping.Key}\", {parameterMapping.Key}.ToString());");
579+
outputPropertyMappingToQuerystring(parameterMapping);
560580
}
561581
}
582+
else
583+
{
584+
outputPropertyMappingToQuerystring(parameterMapping);
585+
}
586+
587+
}
588+
589+
void outputPropertyMappingToQuerystring(ParameterMapping parameterMapping1)
590+
{
591+
if (parameterMapping1.Parameter.SpecialType == SpecialType.System_String && parameterMapping1.Parameter.AllowedStringValues is { Length: > 0 })
592+
{
593+
source.AppendLine($"queryString = queryString.Add(\"{parameterMapping1.Key}\", {parameterMapping1.Key}.Value.ToString());");
594+
}
595+
else
596+
{
597+
source.AppendLine($"queryString = queryString.Add(\"{parameterMapping1.Key}\", {parameterMapping1.Key}.ToString());");
598+
}
562599
}
563600

564601

0 commit comments

Comments
 (0)